• 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/cpp_service_stub_code_emitter.h"
10 #include "util/file.h"
11 #include "util/logger.h"
12 
13 namespace OHOS {
14 namespace HDI {
ResolveDirectory(const String & targetDirectory)15 bool CppServiceStubCodeEmitter::ResolveDirectory(const String& targetDirectory)
16 {
17     if (ast_->GetASTFileType() == ASTFileType::AST_IFACE ||
18         ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) {
19         directory_ = GetFilePath(targetDirectory);
20     } else {
21         return false;
22     }
23 
24     if (!File::CreateParentDir(directory_)) {
25         Logger::E("CppServiceStubCodeEmitter", "Create '%s' failed!", directory_.string());
26         return false;
27     }
28 
29     return true;
30 }
31 
EmitCode()32 void CppServiceStubCodeEmitter::EmitCode()
33 {
34     EmitStubHeaderFile();
35     EmitStubSourceFile();
36 }
37 
EmitStubHeaderFile()38 void CppServiceStubCodeEmitter::EmitStubHeaderFile()
39 {
40     String filePath = String::Format("%s/%s.h", directory_.string(), FileName(stubName_).string());
41     File file(filePath, File::WRITE);
42     StringBuilder sb;
43 
44     EmitLicense(sb);
45     EmitHeadMacro(sb, stubFullName_);
46     sb.Append("\n");
47     EmitStubHeaderInclusions(sb);
48     sb.Append("\n");
49     EmitStubDecl(sb);
50     sb.Append("\n");
51     EmitTailMacro(sb, stubFullName_);
52 
53     String data = sb.ToString();
54     file.WriteData(data.string(), data.GetLength());
55     file.Flush();
56     file.Close();
57 }
58 
EmitStubHeaderInclusions(StringBuilder & sb)59 void CppServiceStubCodeEmitter::EmitStubHeaderInclusions(StringBuilder& sb)
60 {
61     HeaderFile::HeaderFileSet headerFiles;
62 
63     headerFiles.emplace(HeaderFile(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(interfaceName_)));
64     GetHeaderOtherLibInclusions(headerFiles);
65 
66     for (const auto& file : headerFiles) {
67         sb.AppendFormat("%s\n", file.ToString().string());
68     }
69 }
70 
GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles)71 void CppServiceStubCodeEmitter::GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet& headerFiles)
72 {
73     headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "message_parcel"));
74     headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "message_option"));
75     headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "iremote_stub"));
76 }
77 
EmitStubDecl(StringBuilder & sb)78 void CppServiceStubCodeEmitter::EmitStubDecl(StringBuilder& sb)
79 {
80     EmitBeginNamespace(sb);
81     sb.Append("\n");
82     EmitStubUsingNamespace(sb);
83     sb.Append("\n");
84     sb.AppendFormat("class %s : public IRemoteStub<%s> {\n", stubName_.string(), interfaceName_.string());
85     EmitStubBody(sb, g_tab);
86     sb.Append("};\n");
87     sb.Append("\n");
88     EmitEndNamespace(sb);
89 }
90 
EmitStubUsingNamespace(StringBuilder & sb)91 void CppServiceStubCodeEmitter::EmitStubUsingNamespace(StringBuilder& sb)
92 {
93     sb.Append("using namespace OHOS;\n");
94 }
95 
EmitStubBody(StringBuilder & sb,const String & prefix)96 void CppServiceStubCodeEmitter::EmitStubBody(StringBuilder& sb, const String& prefix)
97 {
98     sb.Append("public:\n");
99     EmitStubDestruction(sb, prefix);
100     sb.Append("\n");
101     EmitStubOnRequestDecl(sb, prefix);
102     sb.Append("\n");
103     EmitGetVersionDecl(sb, prefix);
104     sb.Append("\n");
105     EmitStubMethodDecls(sb, prefix);
106 }
107 
EmitStubDestruction(StringBuilder & sb,const String & prefix)108 void CppServiceStubCodeEmitter::EmitStubDestruction(StringBuilder& sb, const String& prefix)
109 {
110     sb.Append(prefix).AppendFormat("virtual ~%s() {}\n", stubName_.string());
111 }
112 
EmitStubOnRequestDecl(StringBuilder & sb,const String & prefix)113 void CppServiceStubCodeEmitter::EmitStubOnRequestDecl(StringBuilder& sb, const String& prefix)
114 {
115     sb.Append(prefix).Append("int32_t OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, ");
116     sb.Append("MessageOption &option) override;\n");
117 }
118 
EmitGetVersionDecl(StringBuilder & sb,const String & prefix)119 void CppServiceStubCodeEmitter::EmitGetVersionDecl(StringBuilder& sb, const String& prefix)
120 {
121     AutoPtr<ASTMethod> method = interface_->GetVersionMethod();
122 
123     StringBuilder paramStr;
124     sb.Append(prefix).AppendFormat("int32_t %s(", method->GetName().string());
125     for (size_t i = 0; i < method->GetParameterNumber(); i++) {
126         AutoPtr<ASTParameter> param = method->GetParameter(i);
127         EmitInterfaceMethodParameter(param, paramStr, "");
128         if (i + 1 < method->GetParameterNumber()) {
129             paramStr.Append(", ");
130         }
131     }
132 
133     paramStr.Append(") override;");
134 
135     sb.Append(SpecificationParam(paramStr, prefix + g_tab));
136     sb.Append("\n");
137 }
138 
EmitStubMethodDecls(StringBuilder & sb,const String & prefix)139 void CppServiceStubCodeEmitter::EmitStubMethodDecls(StringBuilder& sb, const String& prefix)
140 {
141     sb.Append("private:\n");
142     for (size_t i = 0; i < interface_->GetMethodNumber(); i++) {
143         AutoPtr<ASTMethod> method = interface_->GetMethod(i);
144         EmitStubMethodDecl(method, sb, prefix);
145         sb.Append("\n");
146     }
147     EmitStubMethodDecl(interface_->GetVersionMethod(), sb, prefix);
148 }
149 
EmitStubMethodDecl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const String & prefix)150 void CppServiceStubCodeEmitter::EmitStubMethodDecl(const AutoPtr<ASTMethod>& method, StringBuilder& sb,
151     const String& prefix)
152 {
153     sb.Append(prefix).AppendFormat("int32_t %s%s(MessageParcel& %s, MessageParcel& %s, MessageOption& %s);\n",
154         stubName_.string(), method->GetName().string(), dataParcelName_.string(), replyParcelName_.string(),
155         optionName_.string());
156 }
157 
EmitStubSourceFile()158 void CppServiceStubCodeEmitter::EmitStubSourceFile()
159 {
160     String filePath = String::Format("%s/%s.cpp", directory_.string(), FileName(stubName_).string());
161     File file(filePath, File::WRITE);
162     StringBuilder sb;
163 
164     EmitLicense(sb);
165     EmitStubSourceInclusions(sb);
166     sb.Append("\n");
167     EmitBeginNamespace(sb);
168     sb.Append("\n");
169     EmitStubOnRequestMethodImpl(sb, "");
170     sb.Append("\n");
171     EmitGetVersionMethodImpl(sb, "");
172     sb.Append("\n");
173     EmitStubMethodImpls(sb, "");
174     sb.Append("\n");
175     EmitEndNamespace(sb);
176 
177     String data = sb.ToString();
178     file.WriteData(data.string(), data.GetLength());
179     file.Flush();
180     file.Close();
181 }
182 
EmitStubSourceInclusions(StringBuilder & sb)183 void CppServiceStubCodeEmitter::EmitStubSourceInclusions(StringBuilder& sb)
184 {
185     HeaderFile::HeaderFileSet headerFiles;
186     headerFiles.emplace(HeaderFile(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(stubName_)));
187     GetSourceOtherLibInclusions(headerFiles);
188 
189     for (const auto& file : headerFiles) {
190         sb.AppendFormat("%s\n", file.ToString().string());
191     }
192 }
193 
GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles)194 void CppServiceStubCodeEmitter::GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet& headerFiles)
195 {
196     if (!interface_->IsSerializable()) {
197         headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec"));
198     } else {
199         const AST::TypeStringMap& types = ast_->GetTypes();
200         for (const auto& pair : types) {
201             AutoPtr<ASTType> type = pair.second;
202             if (type->GetTypeKind() == TypeKind::TYPE_UNION) {
203                 headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec"));
204                 break;
205             }
206         }
207     }
208 
209     headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base"));
210     headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_log"));
211 }
212 
EmitStubOnRequestMethodImpl(StringBuilder & sb,const String & prefix)213 void CppServiceStubCodeEmitter::EmitStubOnRequestMethodImpl(StringBuilder& sb, const String& prefix)
214 {
215     sb.Append(prefix).AppendFormat("int32_t %s::OnRemoteRequest(uint32_t code, ", stubName_.string());
216     sb.Append("MessageParcel& data, MessageParcel& reply, MessageOption& option)\n");
217     sb.Append(prefix).Append("{\n");
218 
219     sb.Append(prefix + g_tab).Append("switch (code) {\n");
220 
221     for (size_t i = 0; i < interface_->GetMethodNumber(); i++) {
222         AutoPtr<ASTMethod> method = interface_->GetMethod(i);
223         sb.Append(prefix + g_tab + g_tab).AppendFormat("case %s:\n", EmitMethodCmdID(method).string());
224         sb.Append(prefix + g_tab + g_tab + g_tab).AppendFormat("return %sStub%s(data, reply, option);\n",
225             baseName_.string(), method->GetName().string());
226     }
227 
228     AutoPtr<ASTMethod> getVerMethod = interface_->GetVersionMethod();
229     sb.Append(prefix + g_tab + g_tab).AppendFormat("case %s:\n", EmitMethodCmdID(getVerMethod).string());
230     sb.Append(prefix + g_tab + g_tab + g_tab).AppendFormat("return %sStub%s(data, reply, option);\n",
231         baseName_.string(), getVerMethod->GetName().string());
232 
233     sb.Append(prefix + g_tab + g_tab).Append("default: {\n");
234     sb.Append(prefix + g_tab + g_tab + g_tab).Append(
235         "HDF_LOGE(\"%{public}s: not support cmd %{public}d\", __func__, code);\n");
236     sb.Append(prefix + g_tab + g_tab + g_tab).Append(
237         "return IPCObjectStub::OnRemoteRequest(code, data, reply, option);\n");
238     sb.Append(prefix + g_tab + g_tab).Append("}\n");
239     sb.Append(prefix + g_tab).Append("}\n");
240     sb.Append("}\n");
241 }
242 
EmitGetVersionMethodImpl(StringBuilder & sb,const String & prefix)243 void CppServiceStubCodeEmitter::EmitGetVersionMethodImpl(StringBuilder& sb, const String& prefix)
244 {
245     AutoPtr<ASTMethod> method = interface_->GetVersionMethod();
246     sb.Append(prefix).AppendFormat("int32_t %sStub::%s(", baseName_.string(), method->GetName().string());
247     for (size_t i = 0; i < method->GetParameterNumber(); i++) {
248         AutoPtr<ASTParameter> param = method->GetParameter(i);
249         EmitInterfaceMethodParameter(param, sb, "");
250         if (i + 1 < method->GetParameterNumber()) {
251             sb.Append(", ");
252         }
253     }
254 
255     sb.AppendFormat(")\n");
256     sb.Append(prefix).Append("{\n");
257 
258     AutoPtr<ASTParameter> majorParam = method->GetParameter(0);
259     sb.Append(prefix + g_tab).AppendFormat("%s = %s;\n", majorParam->GetName().string(), majorVerName_.string());
260     AutoPtr<ASTParameter> minorParam = method->GetParameter(1);
261     sb.Append(prefix + g_tab).AppendFormat("%s = %s;\n", minorParam->GetName().string(), minorVerName_.string());
262 
263     sb.Append(prefix + g_tab).Append("return HDF_SUCCESS;\n");
264     sb.Append(prefix).Append("}\n");
265 }
266 
EmitStubMethodImpls(StringBuilder & sb,const String & prefix)267 void CppServiceStubCodeEmitter::EmitStubMethodImpls(StringBuilder& sb, const String& prefix)
268 {
269     for (size_t i = 0; i < interface_->GetMethodNumber(); i++) {
270         AutoPtr<ASTMethod> method = interface_->GetMethod(i);
271         EmitStubMethodImpl(method, sb, prefix);
272         sb.Append("\n");
273     }
274 
275     EmitStubMethodImpl(interface_->GetVersionMethod(), sb, prefix);
276 }
277 
EmitStubMethodImpl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const String & prefix)278 void CppServiceStubCodeEmitter::EmitStubMethodImpl(const AutoPtr<ASTMethod>& method, StringBuilder& sb,
279     const String& prefix)
280 {
281     sb.Append(prefix).AppendFormat(
282         "int32_t %s::%s%s(MessageParcel& %s, MessageParcel& %s, MessageOption& %s)\n",
283         stubName_.string(), stubName_.string(), method->GetName().string(),
284         dataParcelName_.string(), replyParcelName_.string(), optionName_.string());
285     sb.Append(prefix).Append("{\n");
286 
287     // read interface token and check it
288     EmitStubReadInterfaceToken(dataParcelName_, sb, prefix + g_tab);
289     sb.Append("\n");
290 
291     for (size_t i = 0; i < method->GetParameterNumber(); i++) {
292         AutoPtr<ASTParameter> param = method->GetParameter(i);
293         if (param->GetAttribute() == ParamAttr::PARAM_IN) {
294             EmitReadMethodParameter(param, dataParcelName_, true, sb, prefix + g_tab);
295             sb.Append("\n");
296         } else {
297             EmitLocalVariable(param, sb, prefix + g_tab);
298             sb.Append("\n");
299         }
300     }
301 
302     EmitStubCallMethod(method, sb, prefix + g_tab);
303     sb.Append("\n");
304 
305     if (!method->IsOneWay()) {
306         for (size_t i = 0; i < method->GetParameterNumber(); i++) {
307             AutoPtr<ASTParameter> param = method->GetParameter(i);
308             if (param->GetAttribute() == ParamAttr::PARAM_OUT) {
309                 EmitWriteMethodParameter(param, replyParcelName_, sb, prefix + g_tab);
310                 sb.Append("\n");
311             }
312         }
313     }
314 
315     sb.Append(prefix + g_tab).Append("return HDF_SUCCESS;\n");
316     sb.Append("}\n");
317 }
318 
EmitStubCallMethod(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const String & prefix)319 void CppServiceStubCodeEmitter::EmitStubCallMethod(const AutoPtr<ASTMethod>& method, StringBuilder& sb,
320     const String& prefix)
321 {
322     sb.Append(prefix).AppendFormat("int32_t %s = %s(", errorCodeName_.string(), method->GetName().string());
323     for (size_t i = 0; i < method->GetParameterNumber(); i++) {
324         AutoPtr<ASTParameter> param = method->GetParameter(i);
325         sb.Append(param->GetName());
326         if (i + 1 < method->GetParameterNumber()) {
327             sb.Append(", ");
328         }
329     }
330     sb.Append(");\n");
331 
332     sb.Append(prefix).AppendFormat("if (%s != HDF_SUCCESS) {\n", errorCodeName_.string());
333     sb.Append(prefix + g_tab).AppendFormat(
334         "HDF_LOGE(\"%%{public}s failed, error code is %%d\", __func__, %s);\n", errorCodeName_.string());
335     sb.Append(prefix + g_tab).AppendFormat("return %s;\n", errorCodeName_.string());
336     sb.Append(prefix).Append("}\n");
337 }
338 
EmitStubReadInterfaceToken(const String & parcelName,StringBuilder & sb,const String & prefix)339 void CppServiceStubCodeEmitter::EmitStubReadInterfaceToken(const String& parcelName, StringBuilder& sb,
340     const String& prefix)
341 {
342     sb.Append(prefix).AppendFormat("if (%s.ReadInterfaceToken() != GetDescriptor()) {\n", parcelName.string());
343     sb.Append(prefix + g_tab).AppendFormat("HDF_LOGE(\"%%{public}s: interface token check failed!\", __func__);\n");
344     sb.Append(prefix + g_tab).AppendFormat("return HDF_ERR_INVALID_PARAM;\n");
345     sb.Append(prefix).Append("}\n");
346 }
347 } // namespace HDI
348 } // namespace OHOS