• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "c_client_proxy_code_emitter.h"
17 #include "util/file.h"
18 #include "util/logger.h"
19 
20 namespace OHOS {
21 namespace Idl {
ResolveDirectory(const std::string & targetDirectory)22 bool CClientProxyCodeEmitter::ResolveDirectory(const std::string &targetDirectory)
23 {
24     if (ast_->GetASTFileType() == ASTFileType::AST_IFACE || ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) {
25         directory_ = GetFileParentPath(targetDirectory);
26     } else {
27         return false;
28     }
29 
30     if (!File::CreateParentDir(directory_)) {
31         Logger::E("CClientProxyCodeEmitter", "Create '%s' failed!", directory_.c_str());
32         return false;
33     }
34 
35     return true;
36 }
37 
EmitCode()38 void CClientProxyCodeEmitter::EmitCode()
39 {
40     switch (mode_) {
41         case GenMode::PASSTHROUGH: {
42             if (!interface_->IsSerializable()) {
43                 EmitPassthroughProxySourceFile();
44             }
45             break;
46         }
47         case GenMode::IPC:
48         case GenMode::KERNEL: {
49             EmitProxySourceFile();
50             break;
51         }
52         default:
53             break;
54     }
55 }
56 
EmitPassthroughProxySourceFile()57 void CClientProxyCodeEmitter::EmitPassthroughProxySourceFile()
58 {
59     std::string filePath =
60         File::AdapterPath(StringHelper::Format("%s/%s.c", directory_.c_str(), FileName(proxyName_).c_str()));
61     File file(filePath, File::WRITE);
62     StringBuilder sb;
63 
64     EmitLicense(sb);
65     EmitPassthroughProxyInclusions(sb);
66     sb.Append("\n");
67     EmitLogTagMacro(sb, FileName(proxyName_));
68     sb.Append("\n");
69     EmitProxyGetMethodImpl(sb);
70     sb.Append("\n");
71     EmitPassthroughGetInstanceMethod(sb);
72     sb.Append("\n");
73     EmitProxyReleaseMethodImpl(sb);
74     sb.Append("\n");
75     EmitPassthroughReleaseInstanceMethod(sb);
76     std::string data = sb.ToString();
77     file.WriteData(data.c_str(), data.size());
78     file.Flush();
79     file.Close();
80 }
81 
EmitPassthroughProxyInclusions(StringBuilder & sb)82 void CClientProxyCodeEmitter::EmitPassthroughProxyInclusions(StringBuilder &sb)
83 {
84     HeaderFile::HeaderFileSet headerFiles;
85     headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
86     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdi_support");
87     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_core_log");
88 
89     for (const auto &file : headerFiles) {
90         sb.AppendFormat("%s\n", file.ToString().c_str());
91     }
92 }
93 
EmitPassthroughGetInstanceMethod(StringBuilder & sb) const94 void CClientProxyCodeEmitter::EmitPassthroughGetInstanceMethod(StringBuilder &sb) const
95 {
96     sb.AppendFormat("struct %s *%sGetInstance(const char *serviceName, bool isStub)\n",
97         interfaceName_.c_str(), interfaceName_.c_str());
98     sb.Append("{\n");
99     EmitProxyLoadOrUnLoadHdiImpl("serviceName", true, sb, TAB);
100     sb.Append(TAB).Append("return NULL;\n");
101     sb.Append("}\n");
102 }
103 
EmitPassthroughReleaseInstanceMethod(StringBuilder & sb) const104 void CClientProxyCodeEmitter::EmitPassthroughReleaseInstanceMethod(StringBuilder &sb) const
105 {
106     sb.AppendFormat("void %sReleaseInstance(const char *serviceName, struct %s *instance, bool isStub)\n",
107         interfaceName_.c_str(), interfaceName_.c_str());
108     sb.Append("{\n");
109     sb.Append(TAB).Append("if (instance == NULL) {\n");
110     sb.Append(TAB).Append(TAB).Append("return;\n");
111     sb.Append(TAB).Append("}\n\n");
112     EmitProxyLoadOrUnLoadHdiImpl("serviceName", false, sb, TAB);
113     sb.Append("}\n");
114 }
115 
EmitProxySourceFile()116 void CClientProxyCodeEmitter::EmitProxySourceFile()
117 {
118     std::string filePath =
119         File::AdapterPath(StringHelper::Format("%s/%s.c", directory_.c_str(), FileName(proxyName_).c_str()));
120     File file(filePath, File::WRITE);
121     StringBuilder sb;
122 
123     EmitLicense(sb);
124     EmitProxyInclusions(sb);
125     sb.Append("\n");
126     EmitLogTagMacro(sb, FileName(proxyName_));
127     sb.Append("\n");
128     EmitProxyDefinition(sb);
129     sb.Append("\n");
130     EmitUtilMethods(sb, true);
131     sb.Append("\n");
132     EmitUtilMethods(sb, false);
133     sb.Append("\n");
134     if (mode_ != GenMode::KERNEL) {
135         EmitProxyCallMethodImpl(sb);
136     } else {
137         EmitProxyKernelCallMethodImpl(sb);
138     }
139     sb.Append("\n");
140     EmitProxyMethodImpls(sb);
141     sb.Append("\n");
142     EmitProxyConstruction(sb);
143     sb.Append("\n");
144     EmitProxyExternalMethodImpl(sb);
145 
146     std::string data = sb.ToString();
147     file.WriteData(data.c_str(), data.size());
148     file.Flush();
149     file.Close();
150 }
151 
EmitProxyInclusions(StringBuilder & sb)152 void CClientProxyCodeEmitter::EmitProxyInclusions(StringBuilder &sb)
153 {
154     HeaderFile::HeaderFileSet headerFiles;
155 
156     headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
157     GetHeaderOtherLibInclusions(headerFiles);
158 
159     for (const auto &file : headerFiles) {
160         sb.AppendFormat("%s\n", file.ToString().c_str());
161     }
162 }
163 
GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles) const164 void CClientProxyCodeEmitter::GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const
165 {
166     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
167     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_core_log");
168     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_sbuf");
169     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "osal_mem");
170     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec");
171 
172     if (mode_ == GenMode::KERNEL) {
173         headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_io_service_if");
174     } else {
175         headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "servmgr_hdi");
176         headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_dlist");
177         if (!interface_->IsSerializable()) {
178             headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdi_support");
179             headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "stub_collector");
180         }
181     }
182 
183     for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
184         for (size_t paramIndex = 0; paramIndex < method->GetParameterNumber(); paramIndex++) {
185             AutoPtr<ASTParameter> param = method->GetParameter(paramIndex);
186             AutoPtr<ASTType> paramType = param->GetType();
187             if ((param->GetAttribute() == ASTParamAttr::PARAM_IN) &&
188                 (paramType->IsInterfaceType() || paramType->HasInnerType(TypeKind::TYPE_INTERFACE))) {
189                 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "stub_collector");
190             }
191         }
192     }
193 }
194 
EmitProxyDefinition(StringBuilder & sb) const195 void CClientProxyCodeEmitter::EmitProxyDefinition(StringBuilder &sb) const
196 {
197     sb.AppendFormat("struct %sProxy {\n", baseName_.c_str());
198     sb.Append(TAB).AppendFormat("struct %s impl;\n", interfaceName_.c_str());
199     if (mode_ == GenMode::KERNEL) {
200         sb.Append(TAB).Append("struct HdfIoService *serv;\n");
201     } else {
202         sb.Append(TAB).Append("struct HdfRemoteService *remote;\n");
203     }
204 
205     sb.Append("};\n");
206 }
207 
EmitProxyCallMethodImpl(StringBuilder & sb) const208 void CClientProxyCodeEmitter::EmitProxyCallMethodImpl(StringBuilder &sb) const
209 {
210     sb.AppendFormat("static int32_t %sProxyCall(struct %s *self, int32_t id, struct HdfSBuf *data,\n",
211         baseName_.c_str(), interfaceName_.c_str());
212     sb.Append(TAB).Append("struct HdfSBuf *reply, bool isOneWay)\n");
213     sb.Append("{\n");
214 
215     std::string remoteName = "remote";
216     sb.Append(TAB).AppendFormat("struct HdfRemoteService *%s = self->AsObject(self);\n", remoteName.c_str());
217     sb.Append(TAB).AppendFormat("if (%s == NULL ||\n", remoteName.c_str());
218     sb.Append(TAB).Append(TAB).AppendFormat("%s->dispatcher == NULL ||\n", remoteName.c_str());
219     sb.Append(TAB).Append(TAB).AppendFormat("%s->dispatcher->Dispatch == NULL ||\n", remoteName.c_str());
220     sb.Append(TAB).Append(TAB).AppendFormat("%s->dispatcher->DispatchAsync == NULL) {\n", remoteName.c_str());
221     sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%{public}s: Invalid HdfRemoteService obj\", __func__);\n");
222     sb.Append(TAB).Append(TAB).Append("return HDF_ERR_INVALID_OBJECT;\n");
223     sb.Append(TAB).Append("}\n");
224 
225     sb.Append(TAB).AppendFormat("if (isOneWay) {\n");
226     sb.Append(TAB).Append(TAB).AppendFormat(
227         "return %s->dispatcher->DispatchAsync(%s, id, data, reply);\n", remoteName.c_str(), remoteName.c_str());
228     sb.Append(TAB).AppendFormat("} else {\n");
229     sb.Append(TAB).Append(TAB).AppendFormat(
230         "return %s->dispatcher->Dispatch(%s, id, data, reply);\n", remoteName.c_str(), remoteName.c_str());
231     sb.Append(TAB).AppendFormat("}\n");
232     sb.Append("}\n");
233 }
234 
EmitProxyKernelCallMethodImpl(StringBuilder & sb) const235 void CClientProxyCodeEmitter::EmitProxyKernelCallMethodImpl(StringBuilder &sb) const
236 {
237     sb.AppendFormat("static int32_t %sProxyCall(struct %s *self, int32_t id, struct HdfSBuf *data,\n",
238         baseName_.c_str(), interfaceName_.c_str());
239     sb.Append(TAB).Append("struct HdfSBuf *reply)\n");
240     sb.Append("{\n");
241 
242     std::string remoteName = "serv";
243     sb.Append(TAB).AppendFormat("struct %sProxy *proxy = CONTAINER_OF(self, struct %sProxy, impl);\n",
244         baseName_.c_str(), baseName_.c_str(), remoteName.c_str());
245     sb.Append(TAB).AppendFormat("struct HdfIoService *%s = proxy->%s;\n", remoteName.c_str(), remoteName.c_str());
246 
247     sb.Append(TAB).AppendFormat("if (%s == NULL ||\n", remoteName.c_str());
248     sb.Append(TAB).Append(TAB).AppendFormat("%s->dispatcher == NULL ||\n", remoteName.c_str());
249     sb.Append(TAB).Append(TAB).AppendFormat("%s->dispatcher->Dispatch == NULL) {\n", remoteName.c_str());
250     sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%{public}s: Invalid HdfRemoteService obj\", __func__);\n");
251     sb.Append(TAB).Append(TAB).Append("return HDF_ERR_INVALID_OBJECT;\n");
252     sb.Append(TAB).Append("}\n\n");
253 
254     sb.Append(TAB).AppendFormat("return %s->dispatcher->Dispatch(", remoteName.c_str());
255     sb.AppendFormat("(struct HdfObject *)&(%s->object), id, data, reply);\n", remoteName.c_str());
256     sb.Append("}\n");
257 }
258 
EmitProxyMethodImpls(StringBuilder & sb)259 void CClientProxyCodeEmitter::EmitProxyMethodImpls(StringBuilder &sb)
260 {
261     for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
262         EmitProxyMethodImpl(method, sb);
263         sb.Append("\n");
264     }
265 
266     EmitProxyMethodImpl(interface_->GetVersionMethod(), sb);
267 
268     if (mode_ != GenMode::KERNEL) {
269         sb.Append("\n");
270         EmitProxyAsObjectMethodImpl(sb);
271     }
272 }
273 
EmitProxyMethodImpl(const AutoPtr<ASTMethod> & method,StringBuilder & sb)274 void CClientProxyCodeEmitter::EmitProxyMethodImpl(const AutoPtr<ASTMethod> &method, StringBuilder &sb)
275 {
276     if (method->GetParameterNumber() == 0) {
277         sb.AppendFormat("static int32_t %sProxy%s(struct %s *self)\n", baseName_.c_str(), method->GetName().c_str(),
278             interfaceName_.c_str());
279     } else {
280         StringBuilder paramStr;
281         paramStr.AppendFormat("static int32_t %sProxy%s(", baseName_.c_str(), method->GetName().c_str());
282         paramStr.AppendFormat("struct %s *self, ", interfaceName_.c_str());
283         for (size_t i = 0; i < method->GetParameterNumber(); i++) {
284             AutoPtr<ASTParameter> param = method->GetParameter(i);
285             EmitInterfaceMethodParameter(param, paramStr, "");
286             if (i + 1 < method->GetParameterNumber()) {
287                 paramStr.Append(", ");
288             }
289         }
290 
291         paramStr.Append(")");
292         sb.Append(SpecificationParam(paramStr, TAB));
293         sb.Append("\n");
294     }
295     EmitProxyMethodBody(method, sb, "");
296 }
297 
EmitProxyMethodBody(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix)298 void CClientProxyCodeEmitter::EmitProxyMethodBody(
299     const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix)
300 {
301     sb.Append(prefix).Append("{\n");
302     sb.Append(prefix + TAB).AppendFormat("int32_t %s = HDF_FAILURE;\n", HdiTypeEmitter::errorCodeName_.c_str());
303 
304     // Local variable definitions must precede all execution statements.
305     EmitMethodNeedLoopVar(method, true, false, sb, prefix + TAB);
306     sb.Append("\n");
307     EmitCreateBuf(HdiTypeEmitter::dataParcelName_, HdiTypeEmitter::replyParcelName_, sb, prefix + TAB);
308     sb.Append("\n");
309     EmitCheckThisPointer(sb, prefix + TAB);
310 
311     if (mode_ != GenMode::KERNEL) {
312         sb.Append("\n");
313         EmitWriteInterfaceToken(HdiTypeEmitter::dataParcelName_, sb, prefix + TAB);
314     }
315 
316     sb.Append("\n");
317     EmitWriteFlagOfNeedSetMem(method, HdiTypeEmitter::dataParcelName_, sb, prefix + TAB);
318     for (size_t i = 0; i < method->GetParameterNumber(); i++) {
319         AutoPtr<ASTParameter> param = method->GetParameter(i);
320         AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(param->GetType());
321         if (typeEmitter == nullptr) {
322             continue;
323         }
324         if (param->GetAttribute() == ASTParamAttr::PARAM_IN) {
325             typeEmitter->EmitCWriteVar(TypeMode::PARAM_IN, param->GetName(), FINISHED_LABEL, sb, prefix + TAB);
326             sb.Append("\n");
327         } else {
328             typeEmitter->EmitCProxyWriteOutVar(param->GetName(), FINISHED_LABEL, sb, prefix + TAB);
329         }
330     }
331 
332     EmitStubCallMethod(method, sb, prefix + TAB);
333     sb.Append("\n");
334 
335     if (!method->IsOneWay()) {
336         for (size_t i = 0; i < method->GetParameterNumber(); i++) {
337             AutoPtr<ASTParameter> param = method->GetParameter(i);
338             if (param->GetAttribute() == ASTParamAttr::PARAM_OUT) {
339                 EmitReadProxyMethodParameter(param, FINISHED_LABEL, sb, prefix + TAB);
340                 sb.Append("\n");
341             }
342         }
343     }
344 
345     sb.Append(prefix).AppendFormat("%s:\n", FINISHED_LABEL);
346     EmitReleaseBuf(HdiTypeEmitter::dataParcelName_, HdiTypeEmitter::replyParcelName_, sb, prefix + TAB);
347 
348     sb.Append(prefix + TAB).AppendFormat("return %s;\n", HdiTypeEmitter::errorCodeName_.c_str());
349     sb.Append("}\n");
350 }
351 
EmitCreateBuf(const std::string & dataBufName,const std::string & replyBufName,StringBuilder & sb,const std::string & prefix) const352 void CClientProxyCodeEmitter::EmitCreateBuf(const std::string &dataBufName,
353     const std::string &replyBufName, StringBuilder &sb, const std::string &prefix) const
354 {
355     if (mode_ == GenMode::KERNEL) {
356         sb.Append(prefix).AppendFormat("struct HdfSBuf *%s = HdfSbufObtainDefaultSize();\n", dataBufName.c_str());
357         sb.Append(prefix).AppendFormat("struct HdfSBuf *%s = HdfSbufObtainDefaultSize();\n", replyBufName.c_str());
358     } else {
359         sb.Append(prefix).AppendFormat("struct HdfSBuf *%s = HdfSbufTypedObtain(SBUF_IPC);\n", dataBufName.c_str());
360         sb.Append(prefix).AppendFormat("struct HdfSBuf *%s = HdfSbufTypedObtain(SBUF_IPC);\n", replyBufName.c_str());
361     }
362 
363     sb.Append("\n");
364     sb.Append(prefix).AppendFormat("if (%s == NULL || %s == NULL) {\n", dataBufName.c_str(), replyBufName.c_str());
365     sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: HdfSubf malloc failed!\", __func__);\n");
366     sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_MALLOC_FAIL;\n", HdiTypeEmitter::errorCodeName_.c_str());
367     sb.Append(prefix + TAB).AppendFormat("goto %s;\n", FINISHED_LABEL);
368     sb.Append(prefix).Append("}\n");
369 }
370 
EmitCheckThisPointer(StringBuilder & sb,const std::string & prefix) const371 void CClientProxyCodeEmitter::EmitCheckThisPointer(StringBuilder &sb, const std::string &prefix) const
372 {
373     sb.Append(prefix).Append("if (self == NULL) {\n");
374     sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: invalid interface object\", __func__);\n");
375     sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_INVALID_OBJECT;\n", HdiTypeEmitter::errorCodeName_.c_str());
376     sb.Append(prefix + TAB).AppendFormat("goto %s;\n", FINISHED_LABEL);
377     sb.Append(prefix).Append("}\n");
378 }
379 
EmitWriteInterfaceToken(const std::string & dataBufName,StringBuilder & sb,const std::string & prefix) const380 void CClientProxyCodeEmitter::EmitWriteInterfaceToken(
381     const std::string &dataBufName, StringBuilder &sb, const std::string &prefix) const
382 {
383     sb.Append(prefix).AppendFormat(
384         "if (!HdfRemoteServiceWriteInterfaceToken(self->AsObject(self), %s)) {\n", dataBufName.c_str());
385     sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: write interface token failed!\", __func__);\n");
386     sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_INVALID_PARAM;\n", HdiTypeEmitter::errorCodeName_.c_str());
387     sb.Append(prefix + TAB).AppendFormat("goto %s;\n", FINISHED_LABEL);
388     sb.Append(prefix).Append("}\n");
389 }
390 
EmitWriteFlagOfNeedSetMem(const AutoPtr<ASTMethod> & method,const std::string & dataBufName,StringBuilder & sb,const std::string & prefix) const391 void CClientProxyCodeEmitter::EmitWriteFlagOfNeedSetMem(const AutoPtr<ASTMethod> &method,
392     const std::string &dataBufName, StringBuilder &sb, const std::string &prefix) const
393 {
394     if (NeedFlag(method)) {
395         sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint8(%s, 1)) {\n", dataBufName.c_str());
396         sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: write flag of memory setting failed!\", __func__);\n");
397         sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_INVALID_PARAM;\n", HdiTypeEmitter::errorCodeName_.c_str());
398         sb.Append(prefix + TAB).AppendFormat("goto %s;\n", FINISHED_LABEL);
399         sb.Append(prefix).Append("}\n\n");
400     }
401 }
402 
EmitReleaseBuf(const std::string & dataBufName,const std::string & replyBufName,StringBuilder & sb,const std::string & prefix) const403 void CClientProxyCodeEmitter::EmitReleaseBuf(const std::string &dataBufName,
404     const std::string &replyBufName, StringBuilder &sb, const std::string &prefix) const
405 {
406     sb.Append(prefix).AppendFormat("if (%s != NULL) {\n", dataBufName.c_str());
407     sb.Append(prefix + TAB).AppendFormat("HdfSbufRecycle(%s);\n", dataBufName.c_str());
408     sb.Append(prefix).Append("}\n");
409     sb.Append(prefix).AppendFormat("if (%s != NULL) {\n", replyBufName.c_str());
410     sb.Append(prefix + TAB).AppendFormat("HdfSbufRecycle(%s);\n", replyBufName.c_str());
411     sb.Append(prefix).Append("}\n");
412 }
413 
EmitReadProxyMethodParameter(const AutoPtr<ASTParameter> & param,const std::string & gotoLabel,StringBuilder & sb,const std::string & prefix) const414 void CClientProxyCodeEmitter::EmitReadProxyMethodParameter(const AutoPtr<ASTParameter> &param,
415     const std::string &gotoLabel, StringBuilder &sb, const std::string &prefix) const
416 {
417     AutoPtr<ASTType> type = param->GetType();
418     AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(type);
419     if (typeEmitter == nullptr) {
420         return;
421     }
422     std::string name = param->GetName();
423     if (type->GetTypeKind() == TypeKind::TYPE_STRING) {
424         std::string cloneName = StringHelper::Format("%sCopy", name.c_str());
425         typeEmitter->EmitCProxyReadVar(cloneName, false, gotoLabel, sb, prefix);
426         sb.Append(prefix).AppendFormat("if (strcpy_s(%s, %sLen, %s) != EOK) {\n", name.c_str(),
427             name.c_str(), cloneName.c_str());
428         sb.Append(prefix + TAB)
429             .AppendFormat("HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.c_str());
430         sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_INVALID_PARAM;\n", HdiTypeEmitter::errorCodeName_.c_str());
431         sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.c_str());
432         sb.Append(prefix).Append("}\n");
433     } else if (type->GetTypeKind() == TypeKind::TYPE_UNION) {
434         std::string cpName = StringHelper::Format("%sCp", name.c_str());
435         typeEmitter->EmitCProxyReadVar(cpName, false, gotoLabel, sb, prefix);
436         sb.Append(prefix).AppendFormat("if (memcpy_s(%s, sizeof(%s), %s, sizeof(%s)) != EOK) {\n",
437             name.c_str(), typeEmitter->EmitCType().c_str(), cpName.c_str(), typeEmitter->EmitCType().c_str());
438         sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: failed to memcpy %s\", __func__);\n",
439             name.c_str());
440         sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
441         sb.Append(prefix).Append("}\n");
442     } else {
443         typeEmitter->EmitCProxyReadVar(name, false, gotoLabel, sb, prefix);
444     }
445 }
446 
EmitStubCallMethod(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix)447 void CClientProxyCodeEmitter::EmitStubCallMethod(
448     const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix)
449 {
450     if (mode_ != GenMode::KERNEL) {
451         sb.Append(prefix).AppendFormat("%s = %sCall(self, %s, %s, %s, %s);\n", HdiTypeEmitter::errorCodeName_.c_str(),
452             proxyName_.c_str(), EmitMethodCmdID(method).c_str(), HdiTypeEmitter::dataParcelName_.c_str(),
453             HdiTypeEmitter::replyParcelName_.c_str(),
454             method->IsOneWay() ? "true" : "false");
455     } else {
456         sb.Append(prefix).AppendFormat("%s = %sCall(self, %s, %s, %s);\n", HdiTypeEmitter::errorCodeName_.c_str(),
457             proxyName_.c_str(), EmitMethodCmdID(method).c_str(), HdiTypeEmitter::dataParcelName_.c_str(),
458             HdiTypeEmitter::replyParcelName_.c_str());
459     }
460     sb.Append(prefix).AppendFormat("if (%s != HDF_SUCCESS) {\n", HdiTypeEmitter::errorCodeName_.c_str());
461     sb.Append(prefix + TAB).AppendFormat(
462         "HDF_LOGE(\"%%{public}s: call failed! error code is %%{public}d\", __func__, %s);\n",
463         HdiTypeEmitter::errorCodeName_.c_str());
464     sb.Append(prefix + TAB).AppendFormat("goto %s;\n", FINISHED_LABEL);
465     sb.Append(prefix).Append("}\n");
466 }
467 
EmitProxyAsObjectMethodImpl(StringBuilder & sb) const468 void CClientProxyCodeEmitter::EmitProxyAsObjectMethodImpl(StringBuilder &sb) const
469 {
470     sb.AppendFormat("static struct HdfRemoteService *%sProxyAsObject(struct %s *self)\n", baseName_.c_str(),
471         interfaceName_.c_str());
472     sb.Append("{\n");
473     sb.Append(TAB).Append("if (self == NULL) {\n");
474     sb.Append(TAB).Append(TAB).Append("return NULL;\n");
475     sb.Append(TAB).Append("}\n");
476     sb.Append(TAB).AppendFormat(
477         "struct %sProxy *proxy = CONTAINER_OF(self, struct %sProxy, impl);\n", baseName_.c_str(), baseName_.c_str());
478     sb.Append(TAB).Append("return proxy->remote;\n");
479     sb.Append("}\n");
480 }
481 
EmitProxyConstruction(StringBuilder & sb) const482 void CClientProxyCodeEmitter::EmitProxyConstruction(StringBuilder &sb) const
483 {
484     std::string objName = "impl";
485     sb.AppendFormat(
486         "static void %sProxyConstruct(struct %s *%s)\n", baseName_.c_str(), interfaceName_.c_str(), objName.c_str());
487     sb.Append("{\n");
488 
489     for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
490         sb.Append(TAB).AppendFormat("%s->%s = %sProxy%s;\n", objName.c_str(), method->GetName().c_str(),
491             baseName_.c_str(), method->GetName().c_str());
492     }
493 
494     AutoPtr<ASTMethod> getVerMethod = interface_->GetVersionMethod();
495     sb.Append(TAB).AppendFormat("%s->%s = %sProxy%s;\n", objName.c_str(), getVerMethod->GetName().c_str(),
496         baseName_.c_str(), getVerMethod->GetName().c_str());
497 
498     if (mode_ != GenMode::KERNEL) {
499         sb.Append(TAB).AppendFormat("%s->AsObject = %sProxyAsObject;\n", objName.c_str(), baseName_.c_str());
500     }
501 
502     sb.Append("}\n");
503 }
504 
EmitProxyExternalMethodImpl(StringBuilder & sb)505 void CClientProxyCodeEmitter::EmitProxyExternalMethodImpl(StringBuilder &sb)
506 {
507     if (mode_ == GenMode::KERNEL) {
508         EmitKernelProxyExternalMethodImpl(sb);
509     } else if (interface_->IsSerializable()) {
510         EmitSerialProxyExternalMethodImpl(sb);
511     } else {
512         EmitProxyExternalMethod(sb);
513     }
514 }
515 
EmitKernelProxyExternalMethodImpl(StringBuilder & sb)516 void CClientProxyCodeEmitter::EmitKernelProxyExternalMethodImpl(StringBuilder &sb)
517 {
518     std::string remoteName = "serv";
519 
520     EmitKernelProxyGetMethodImpl(sb);
521     sb.Append("\n");
522     EmitKernelProxyGetInstanceMethodImpl(remoteName, sb);
523     sb.Append("\n");
524     EmitKernelProxyReleaseMethodImpl(remoteName, "HdfIoServiceRecycle", sb);
525 }
526 
EmitKernelProxyGetMethodImpl(StringBuilder & sb) const527 void CClientProxyCodeEmitter::EmitKernelProxyGetMethodImpl(StringBuilder &sb) const
528 {
529     sb.AppendFormat("struct %s *%sGet()\n", interfaceName_.c_str(), interfaceName_.c_str());
530     sb.Append("{\n");
531     sb.Append(TAB).AppendFormat("return %sGetInstance(\"%s\");\n", interfaceName_.c_str(),
532         FileName(implName_).c_str());
533     sb.Append("}\n");
534 }
535 
EmitKernelProxyGetInstanceMethodImpl(const std::string & remoteName,StringBuilder & sb) const536 void CClientProxyCodeEmitter::EmitKernelProxyGetInstanceMethodImpl(const std::string &remoteName,
537     StringBuilder &sb) const
538 {
539     std::string objName = "client";
540     std::string serMajorName = "serMajorVer";
541     std::string serMinorName = "serMinorVer";
542     std::string serviceName = "serviceName";
543 
544     sb.AppendFormat("struct %s *%sGetInstance(const char* %s)\n", interfaceName_.c_str(), interfaceName_.c_str(),
545         serviceName.c_str());
546     sb.Append("{\n");
547     EmitProxyGetRemoteService(remoteName, serviceName, sb, TAB);
548     sb.Append("\n");
549     EmitProxyCreateProxyObject(objName, remoteName, "HdfIoServiceRecycle", sb, TAB);
550     sb.Append("\n");
551     EmitProxyCheckVersion(objName, serMajorName, serMinorName, sb, TAB);
552     sb.Append("\n");
553     sb.Append(TAB).AppendFormat("return %s;\n", objName.c_str());
554     sb.Append("}\n");
555 }
556 
EmitKernelProxyReleaseMethodImpl(const std::string & remoteName,const std::string & recycleFuncName,StringBuilder & sb) const557 void CClientProxyCodeEmitter::EmitKernelProxyReleaseMethodImpl(
558     const std::string &remoteName, const std::string &recycleFuncName, StringBuilder &sb) const
559 {
560     sb.AppendFormat("void %sRelease(struct %s *instance)\n", interfaceName_.c_str(), interfaceName_.c_str());
561     sb.Append("{\n");
562     sb.Append(TAB).Append("if (instance == NULL) {\n");
563     sb.Append(TAB).Append(TAB).Append("return;\n");
564     sb.Append(TAB).Append("}\n");
565     sb.Append(TAB).AppendFormat("struct %sProxy *proxy = CONTAINER_OF(instance, struct %sProxy, impl);\n",
566         baseName_.c_str(), baseName_.c_str());
567     sb.Append(TAB).AppendFormat("%s(proxy->%s);\n", recycleFuncName.c_str(), remoteName.c_str());
568     sb.Append(TAB).Append("OsalMemFree(proxy);\n");
569     sb.Append("}\n");
570 }
571 
EmitSerialProxyExternalMethodImpl(StringBuilder & sb)572 void CClientProxyCodeEmitter::EmitSerialProxyExternalMethodImpl(StringBuilder &sb)
573 {
574     std::string serMajorName = "serMajorVer";
575     std::string serMinorName = "serMinorVer";
576     std::string remoteName = "remote";
577 
578     EmitIfaceProxyGetMethodImpl(serMajorName, serMinorName, remoteName, sb);
579     sb.Append("\n");
580 
581     if (interface_->IsCallback()) {
582         EmitCbProxyReleaseMethodImpl(remoteName, "HdfRemoteServiceRecycle", sb);
583     } else {
584         EmitIfaceProxyReleaseMethodImpl(remoteName, "HdfRemoteServiceRecycle", sb);
585     }
586 }
587 
EmitIfaceProxyGetMethodImpl(const std::string & serMajorName,const std::string & serMinorName,const std::string & remoteName,StringBuilder & sb)588 void CClientProxyCodeEmitter::EmitIfaceProxyGetMethodImpl(const std::string &serMajorName,
589     const std::string &serMinorName, const std::string &remoteName, StringBuilder &sb)
590 {
591     std::string objName = "client";
592     sb.AppendFormat("struct %s *%sGet(struct HdfRemoteService *%s)\n", interfaceName_.c_str(), interfaceName_.c_str(),
593         remoteName.c_str());
594     sb.Append("{\n");
595     sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", remoteName.c_str());
596     sb.Append(TAB).Append(TAB).AppendFormat("HDF_LOGE(\"%%{public}s: remote is null\", __func__);\n");
597     sb.Append(TAB).Append(TAB).Append("return NULL;\n");
598     sb.Append(TAB).Append("}\n\n");
599     EmitProxySetInterfaceDesc(remoteName, "HdfRemoteServiceRecycle", sb, TAB);
600     sb.Append("\n");
601     EmitProxyCreateProxyObject(objName, remoteName, "HdfRemoteServiceRecycle", sb, TAB);
602     sb.Append("\n");
603     EmitProxyCheckVersion(objName, serMajorName, serMinorName, sb, TAB);
604     sb.Append("\n");
605     sb.Append(TAB).AppendFormat("return %s;\n", objName.c_str());
606     sb.Append("}\n");
607 }
608 
EmitIfaceProxyReleaseMethodImpl(const std::string & remoteName,const std::string & recycleFuncName,StringBuilder & sb) const609 void CClientProxyCodeEmitter::EmitIfaceProxyReleaseMethodImpl(
610     const std::string &remoteName, const std::string &recycleFuncName, StringBuilder &sb) const
611 {
612     std::string implReleaseMethodName = StringHelper::Format("%sImplRelease", interfaceName_.c_str());
613     sb.AppendFormat("void %s(struct %s *instance) __attribute__((weak));\n", implReleaseMethodName.c_str(),
614         interfaceName_.c_str());
615     sb.AppendFormat("void %sRelease(struct %s *instance, bool isStub)\n", interfaceName_.c_str(),
616         interfaceName_.c_str());
617     sb.Append("{\n");
618     sb.Append(TAB).Append("if (instance == NULL) {\n");
619     sb.Append(TAB).Append(TAB).Append("return;\n");
620     sb.Append(TAB).Append("}\n");
621 
622     sb.Append(TAB).Append("if (isStub) {\n");
623     sb.Append(TAB).Append(TAB).AppendFormat("if (%s != NULL) {\n", implReleaseMethodName.c_str());
624     sb.Append(TAB).Append(TAB).Append(TAB).AppendFormat("%s(instance);\n", implReleaseMethodName.c_str());
625     sb.Append(TAB).Append(TAB).Append("}\n");
626     sb.Append(TAB).Append(TAB).Append("return;\n");
627     sb.Append(TAB).Append("}\n");
628 
629     sb.Append(TAB).AppendFormat("struct %sProxy *proxy = CONTAINER_OF(instance, struct %sProxy, impl);\n",
630         baseName_.c_str(), baseName_.c_str());
631     sb.Append(TAB).AppendFormat("%s(proxy->%s);\n", recycleFuncName.c_str(), remoteName.c_str());
632     sb.Append(TAB).Append("OsalMemFree(proxy);\n");
633     sb.Append("}\n");
634 }
635 
EmitCbProxyReleaseMethodImpl(const std::string & remoteName,const std::string & recycleFuncName,StringBuilder & sb) const636 void CClientProxyCodeEmitter::EmitCbProxyReleaseMethodImpl(const std::string &remoteName,
637     const std::string &recycleFuncName, StringBuilder &sb) const
638 {
639     sb.AppendFormat("void %sRelease(struct %s *instance)\n", interfaceName_.c_str(), interfaceName_.c_str());
640     sb.Append("{\n");
641     sb.Append(TAB).Append("if (instance == NULL) {\n");
642     sb.Append(TAB).Append(TAB).Append("return;\n");
643     sb.Append(TAB).Append("}\n\n");
644     sb.Append(TAB).AppendFormat("struct %sProxy *proxy = CONTAINER_OF(instance, struct %sProxy, impl);\n",
645         baseName_.c_str(), baseName_.c_str());
646     sb.Append(TAB).AppendFormat("%s(proxy->%s);\n", recycleFuncName.c_str(), remoteName.c_str());
647     sb.Append(TAB).Append("OsalMemFree(proxy);\n");
648     sb.Append("}\n");
649 }
650 
EmitProxyExternalMethod(StringBuilder & sb)651 void CClientProxyCodeEmitter::EmitProxyExternalMethod(StringBuilder &sb)
652 {
653     std::string remoteName = "remote";
654     std::string serviceName = "serviceName";
655 
656     EmitProxyGetMethodImpl(sb);
657     sb.Append("\n");
658     EmitProxyGetInstanceMethodImpl(remoteName, serviceName, sb);
659     sb.Append("\n");
660     EmitProxyReleaseMethodImpl(sb);
661     sb.Append("\n");
662     EmitProxyReleaseInstanceMethodImpl(serviceName, remoteName, "HdfRemoteServiceRecycle", sb);
663 }
664 
EmitProxyGetMethodImpl(StringBuilder & sb) const665 void CClientProxyCodeEmitter::EmitProxyGetMethodImpl(StringBuilder &sb) const
666 {
667     sb.AppendFormat("struct %s *%sGet(bool isStub)\n", interfaceName_.c_str(), interfaceName_.c_str());
668     sb.Append("{\n");
669     sb.Append(TAB).AppendFormat("return %sGetInstance(\"%s\", isStub);\n", interfaceName_.c_str(),
670         FileName(implName_).c_str());
671     sb.Append("}\n");
672 }
673 
EmitProxyGetInstanceMethodImpl(const std::string & remoteName,const std::string & serviceName,StringBuilder & sb) const674 void CClientProxyCodeEmitter::EmitProxyGetInstanceMethodImpl(const std::string &remoteName,
675     const std::string &serviceName, StringBuilder &sb) const
676 {
677     std::string objName = "client";
678     std::string serMajorName = "serMajorVer";
679     std::string serMinorName = "serMinorVer";
680 
681     sb.AppendFormat("struct %s *%sGetInstance(const char *%s, bool isStub)\n", interfaceName_.c_str(),
682         interfaceName_.c_str(), serviceName.c_str());
683     sb.Append("{\n");
684     EmitProxyLoadOrUnLoadHdiImpl(serviceName, true, sb, TAB);
685     sb.Append("\n");
686     EmitProxyGetRemoteService(remoteName, serviceName, sb, TAB);
687     sb.Append("\n");
688     EmitProxySetInterfaceDesc(remoteName, "HdfRemoteServiceRecycle", sb, TAB);
689     sb.Append("\n");
690     EmitProxyCreateProxyObject(objName, remoteName, "HdfRemoteServiceRecycle", sb, TAB);
691     sb.Append("\n");
692     EmitProxyCheckVersion(objName, serMajorName, serMinorName, sb, TAB);
693     sb.Append("\n");
694     sb.Append(TAB).AppendFormat("return %s;\n", objName.c_str());
695     sb.Append("}\n");
696 }
697 
EmitProxyGetRemoteService(const std::string & remoteName,const std::string & serviceName,StringBuilder & sb,const std::string & prefix) const698 void CClientProxyCodeEmitter::EmitProxyGetRemoteService(const std::string &remoteName,
699     const std::string &serviceName, StringBuilder &sb, const std::string &prefix) const
700 {
701     if (mode_ != GenMode::KERNEL) {
702         sb.Append(prefix).Append("struct HDIServiceManager *serviceMgr = HDIServiceManagerGet();\n");
703         sb.Append(prefix).Append("if (serviceMgr == NULL) {\n");
704         sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: HDIServiceManager not found!\", __func__);\n");
705         sb.Append(prefix + TAB).Append("return NULL;\n");
706         sb.Append(prefix).Append("}\n\n");
707         sb.Append(prefix).AppendFormat("struct HdfRemoteService *%s = ", remoteName.c_str());
708         sb.AppendFormat("serviceMgr->GetService(serviceMgr, %s);\n", serviceName.c_str());
709         sb.Append(prefix).Append("HDIServiceManagerRelease(serviceMgr);\n");
710         sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", remoteName.c_str());
711         sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: failed to get remote!\", __func__);\n");
712         sb.Append(prefix + TAB).Append("return NULL;\n");
713         sb.Append(prefix).Append("}\n");
714     } else {
715         sb.Append(prefix).AppendFormat("struct HdfIoService *%s = ", remoteName.c_str());
716         sb.AppendFormat("HdfIoServiceBind(%s);\n", serviceName.c_str());
717         sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", remoteName.c_str());
718         sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: failed to get io service!\", __func__);\n");
719         sb.Append(prefix + TAB).Append("return NULL;\n");
720         sb.Append(prefix).Append("}\n");
721     }
722 }
723 
EmitProxySetInterfaceDesc(const std::string & remoteName,const std::string & recycleFuncName,StringBuilder & sb,const std::string & prefix) const724 void CClientProxyCodeEmitter::EmitProxySetInterfaceDesc(const std::string &remoteName,
725     const std::string &recycleFuncName, StringBuilder &sb, const std::string &prefix) const
726 {
727     sb.Append(prefix).AppendFormat("if (!HdfRemoteServiceSetInterfaceDesc(%s, %s)) {\n", remoteName.c_str(),
728         EmitDescMacroName().c_str());
729     sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: set interface token failed!\", __func__);\n");
730     sb.Append(prefix + TAB).AppendFormat("%s(%s);\n", recycleFuncName.c_str(), remoteName.c_str());
731     sb.Append(prefix + TAB).Append("return NULL;\n");
732     sb.Append(prefix).Append("}\n");
733 }
734 
EmitProxyCreateProxyObject(const std::string & clientObjName,const std::string & remoteName,const std::string & recycleFuncName,StringBuilder & sb,const std::string & prefix) const735 void CClientProxyCodeEmitter::EmitProxyCreateProxyObject(const std::string &clientObjName,
736     const std::string &remoteName, const std::string &recycleFuncName, StringBuilder &sb,
737     const std::string &prefix) const
738 {
739     sb.Append(prefix).AppendFormat("struct %sProxy *proxy = (struct %sProxy *)OsalMemCalloc(sizeof(struct %sProxy));\n",
740         baseName_.c_str(), baseName_.c_str(), baseName_.c_str());
741     sb.Append(prefix).Append("if (proxy == NULL) {\n");
742     sb.Append(prefix + TAB)
743         .AppendFormat("HDF_LOGE(\"%%{public}s: malloc %s proxy failed!\", __func__);\n", interfaceName_.c_str());
744     if (!interface_->IsSerializable()) {
745         sb.Append(prefix + TAB).AppendFormat("%s(%s);\n", recycleFuncName.c_str(), remoteName.c_str());
746     }
747     sb.Append(prefix + TAB).Append("return NULL;\n");
748     sb.Append(prefix).Append("}\n");
749     sb.Append("\n");
750     sb.Append(prefix).AppendFormat("proxy->%s = %s;\n", remoteName.c_str(), remoteName.c_str());
751     sb.Append(prefix).AppendFormat("%sProxyConstruct(&proxy->impl);\n", baseName_.c_str());
752     sb.Append(prefix).AppendFormat("struct %s *%s = &proxy->impl;\n", interfaceName_.c_str(), clientObjName.c_str());
753 }
754 
EmitProxyCheckVersion(const std::string & clientObjName,const std::string & serMajorName,const std::string & serMinorName,StringBuilder & sb,const std::string & prefix) const755 void CClientProxyCodeEmitter::EmitProxyCheckVersion(const std::string &clientObjName, const std::string &serMajorName,
756     const std::string &serMinorName, StringBuilder &sb, const std::string &prefix) const
757 {
758     sb.Append(prefix).AppendFormat("uint32_t %s = 0;\n", serMajorName.c_str());
759     sb.Append(prefix).AppendFormat("uint32_t %s = 0;\n", serMinorName.c_str());
760     sb.Append(prefix).AppendFormat("int32_t %s = %s->GetVersion(%s, &%s, &%s);\n",
761         HdiTypeEmitter::errorCodeName_.c_str(), clientObjName.c_str(),
762         clientObjName.c_str(), serMajorName.c_str(), serMinorName.c_str());
763     sb.Append(prefix).AppendFormat("if (%s != HDF_SUCCESS) {\n", HdiTypeEmitter::errorCodeName_.c_str());
764     sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: get version failed!\", __func__);\n");
765     if (mode_ == GenMode::KERNEL || interface_->IsCallback()) {
766         sb.Append(prefix + TAB).AppendFormat("%sRelease(%s);\n", interfaceName_.c_str(), clientObjName.c_str());
767     } else if (mode_ == GenMode::PASSTHROUGH || loadVersionCheck_) {
768         sb.Append(prefix + TAB).AppendFormat("%sRelease(%s, true);\n", interfaceName_.c_str(), clientObjName.c_str());
769     } else {
770         sb.Append(prefix + TAB).AppendFormat("%sRelease(%s, false);\n", interfaceName_.c_str(), clientObjName.c_str());
771     }
772 
773     sb.Append(prefix + TAB).Append("return NULL;\n").Append(prefix).Append("}\n\n");
774     sb.Append(prefix).AppendFormat("if (%s != %s) {\n", serMajorName.c_str(), majorVerName_.c_str());
775     sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s:check version failed! ");
776     sb.Append("version of service:%u.%u, version of client:%u.%u\", __func__,\n");
777     sb.Append(prefix + TAB + TAB).AppendFormat("%s, %s, %s, %s);\n", serMajorName.c_str(), serMinorName.c_str(),
778         majorVerName_.c_str(), minorVerName_.c_str());
779     if (mode_ == GenMode::KERNEL || interface_->IsCallback()) {
780         sb.Append(prefix + TAB).AppendFormat("%sRelease(%s);\n", interfaceName_.c_str(), clientObjName.c_str());
781     } else if (mode_ == GenMode::PASSTHROUGH || loadVersionCheck_) {
782         sb.Append(prefix + TAB).AppendFormat("%sRelease(%s, true);\n", interfaceName_.c_str(), clientObjName.c_str());
783     } else {
784         sb.Append(prefix + TAB).AppendFormat("%sRelease(%s, false);\n", interfaceName_.c_str(), clientObjName.c_str());
785     }
786     sb.Append(prefix + TAB).Append("return NULL;\n").Append(prefix).Append("}\n\n");
787     sb.Append(prefix).AppendFormat("if (%s < %s) {\n", serMinorName.c_str(), minorVerName_.c_str());
788     sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s:check version failed! ");
789     sb.Append("client minor version(%u) should be less \"\n");
790     sb.Append(prefix + TAB + TAB).Append("\"or equal to server minor version(%u).");
791     sb.AppendFormat("\", __func__, %s, %s);\n", minorVerName_.c_str(), serMinorName.c_str());
792     if (mode_ == GenMode::KERNEL || interface_->IsCallback()) {
793         sb.Append(prefix + TAB).AppendFormat("%sRelease(%s);\n", interfaceName_.c_str(), clientObjName.c_str());
794     } else if (mode_ == GenMode::PASSTHROUGH || loadVersionCheck_) {
795         sb.Append(prefix + TAB).AppendFormat("%sRelease(%s, true);\n", interfaceName_.c_str(), clientObjName.c_str());
796     } else {
797         sb.Append(prefix + TAB).AppendFormat("%sRelease(%s, false);\n", interfaceName_.c_str(), clientObjName.c_str());
798     }
799     sb.Append(prefix + TAB).Append("return NULL;\n").Append(prefix).Append("}\n");
800 }
801 
EmitProxyReleaseMethodImpl(StringBuilder & sb) const802 void CClientProxyCodeEmitter::EmitProxyReleaseMethodImpl(StringBuilder &sb) const
803 {
804     sb.AppendFormat(
805         "void %sRelease(struct %s *instance, bool isStub)\n", interfaceName_.c_str(), interfaceName_.c_str());
806     sb.Append("{\n");
807     sb.Append(TAB).AppendFormat(
808         "%sReleaseInstance(\"%s\", instance, isStub);\n", interfaceName_.c_str(), FileName(implName_).c_str());
809     sb.Append("}\n");
810 }
811 
EmitProxyReleaseInstanceMethodImpl(const std::string & serviceName,const std::string & remoteName,const std::string & recycleFuncName,StringBuilder & sb)812 void CClientProxyCodeEmitter::EmitProxyReleaseInstanceMethodImpl(const std::string &serviceName,
813     const std::string &remoteName, const std::string &recycleFuncName, StringBuilder &sb)
814 {
815     sb.AppendFormat("void %sReleaseInstance(const char *%s, struct %s *instance, bool isStub)\n",
816         interfaceName_.c_str(), serviceName.c_str(), interfaceName_.c_str());
817     sb.Append("{\n");
818     sb.Append(TAB).Append("if (instance == NULL) {\n");
819     sb.Append(TAB).Append(TAB).Append("return;\n");
820     sb.Append(TAB).Append("}\n\n");
821     EmitProxyLoadOrUnLoadHdiImpl(serviceName, false, sb, TAB);
822     sb.Append("\n");
823     sb.Append(TAB).AppendFormat("struct %sProxy *proxy = CONTAINER_OF(instance, struct %sProxy, impl);\n",
824         baseName_.c_str(), baseName_.c_str());
825     sb.Append(TAB).AppendFormat("%s(proxy->%s);\n", recycleFuncName.c_str(), remoteName.c_str());
826     sb.Append(TAB).Append("OsalMemFree(proxy);\n");
827     sb.Append("}\n");
828 }
829 
EmitProxyLoadOrUnLoadHdiImpl(const std::string & serviceName,bool isLoad,StringBuilder & sb,const std::string & prefix) const830 void CClientProxyCodeEmitter::EmitProxyLoadOrUnLoadHdiImpl(const std::string &serviceName, bool isLoad,
831     StringBuilder &sb, const std::string &prefix) const
832 {
833     std::string instName = "instName";
834     sb.Append(prefix).Append("if (isStub) {\n");
835     sb.Append(prefix + TAB).AppendFormat("const char *%s = %s;\n", instName.c_str(), serviceName.c_str());
836     sb.Append(prefix + TAB)
837         .AppendFormat("if (strcmp(%s, \"%s\") == 0) {\n", instName.c_str(), FileName(implName_).c_str());
838     sb.Append(prefix + TAB + TAB).AppendFormat("%s = \"service\";\n", instName.c_str());
839     sb.Append(prefix + TAB).Append("}\n");
840     if (isLoad) {
841         std::string objName = "inst";
842         std::string serMajorName = "serMajorVer";
843         std::string serMinorName = "serMinorVer";
844 
845         sb.Append(prefix + TAB).AppendFormat("struct %s *inst = LoadHdiImpl(%s, %s);\n",
846             interfaceName_.c_str(), EmitDescMacroName().c_str(), instName.c_str());
847         sb.Append(prefix + TAB).Append("if (inst == NULL) {\n");
848         sb.Append(prefix + TAB + TAB).AppendFormat("HDF_LOGE(\"%%{public}s, failed to load hdi "
849             "impl %%{public}s!\", __func__, %s);\n", EmitDescMacroName().c_str());
850 
851         sb.Append(prefix + TAB + TAB).Append("return NULL;\n").Append(prefix + TAB).Append("}\n");
852         sb.Append(prefix + TAB).Append("if (inst->GetVersion == NULL) {\n");
853 
854         sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s: "
855             "GetVersion is not implemented!\", __func__);\n");
856         if (mode_ == GenMode::KERNEL) {
857             sb.Append(prefix + TAB + TAB).AppendFormat("%sRelease(%s);\n", \
858                 interfaceName_.c_str(), objName.c_str());
859         } else if (interface_->IsCallback()) {
860             sb.Append(prefix + TAB + TAB).AppendFormat("%sRelease(%s);\n", \
861                 interfaceName_.c_str(), objName.c_str());
862         } else if (mode_ == GenMode::PASSTHROUGH || isLoad) {
863             sb.Append(prefix + TAB + TAB).AppendFormat("%sRelease(%s, true);\n", \
864                 interfaceName_.c_str(), objName.c_str());
865         } else {
866             sb.Append(prefix + TAB + TAB).AppendFormat("%sRelease(%s, false);\n", \
867                 interfaceName_.c_str(), objName.c_str());
868         }
869         sb.Append(prefix + TAB + TAB).Append("return NULL;\n").Append(prefix + TAB).Append("}\n");
870         loadVersionCheck_ = true;
871         EmitProxyCheckVersion(objName, serMajorName, serMinorName, sb, prefix + TAB);
872         loadVersionCheck_ = false;
873         sb.Append(prefix + TAB).Append("return inst;\n");
874     } else {
875         sb.Append(prefix + TAB).AppendFormat("UnloadHdiImpl(%s, %s, instance);\n",
876             EmitDescMacroName().c_str(), instName.c_str());
877         sb.Append(prefix + TAB).Append("return;\n");
878     }
879     sb.Append(prefix).Append("}\n");
880 }
881 
EmitUtilMethods(StringBuilder & sb,bool isDecl)882 void CClientProxyCodeEmitter::EmitUtilMethods(StringBuilder &sb, bool isDecl)
883 {
884     UtilMethodMap methods;
885     for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
886         for (size_t paramIndex = 0; paramIndex < method->GetParameterNumber(); paramIndex++) {
887             AutoPtr<ASTParameter> param = method->GetParameter(paramIndex);
888             AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(param->GetType());
889             if (typeEmitter == nullptr) {
890                 continue;
891             }
892             if (param->GetAttribute() == ASTParamAttr::PARAM_IN) {
893                 typeEmitter->EmitCWriteMethods(methods, "", "", isDecl);
894             } else {
895                 typeEmitter->EmitCReadMethods(methods, "", "", isDecl);
896             }
897         }
898     }
899     EmitUtilMethodMap(sb, methods);
900 }
901 } // namespace Idl
902 } // namespace OHOS
903