1 /*
2 * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "codegen/c_interface_code_emitter.h"
10 #include "util/file.h"
11 #include "util/logger.h"
12
13 namespace OHOS {
14 namespace HDI {
ResolveDirectory(const std::string & targetDirectory)15 bool CInterfaceCodeEmitter::ResolveDirectory(const std::string &targetDirectory)
16 {
17 if (ast_->GetASTFileType() == ASTFileType::AST_IFACE || ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) {
18 directory_ = GetFileParentPath(targetDirectory);
19 } else {
20 return false;
21 }
22
23 if (!File::CreateParentDir(directory_)) {
24 Logger::E("CInterfaceCodeEmitter", "Create '%s' failed!", directory_.c_str());
25 return false;
26 }
27
28 return true;
29 }
30
EmitCode()31 void CInterfaceCodeEmitter::EmitCode()
32 {
33 switch (mode_) {
34 case GenMode::LOW: {
35 EmitLowModeInterfaceHeaderFile();
36 break;
37 }
38 case GenMode::PASSTHROUGH:
39 case GenMode::IPC:
40 case GenMode::KERNEL: {
41 EmitInterfaceHeaderFile();
42 break;
43 }
44 default:
45 break;
46 }
47 }
48
EmitLowModeInterfaceHeaderFile()49 void CInterfaceCodeEmitter::EmitLowModeInterfaceHeaderFile()
50 {
51 std::string filePath =
52 File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(interfaceName_).c_str()));
53 File file(filePath, File::WRITE);
54 StringBuilder sb;
55
56 EmitLicense(sb);
57 EmitHeadMacro(sb, interfaceFullName_);
58 sb.Append("\n");
59 EmitImportInclusions(sb);
60 sb.Append("\n");
61 EmitHeadExternC(sb);
62 sb.Append("\n");
63 EmitInterfaceVersionMacro(sb);
64 if (!interface_->IsSerializable()) {
65 sb.Append("\n");
66 EmitPreDeclaration(sb);
67 }
68 sb.Append("\n");
69 EmitInterfaceDefinition(sb);
70 if (!interface_->IsSerializable()) {
71 sb.Append("\n");
72 EmitLowModeExternalMethod(sb);
73 }
74 sb.Append("\n");
75 EmitTailExternC(sb);
76 sb.Append("\n");
77 EmitTailMacro(sb, interfaceFullName_);
78
79 std::string data = sb.ToString();
80 file.WriteData(data.c_str(), data.size());
81 file.Flush();
82 file.Close();
83 }
84
EmitLowModeExternalMethod(StringBuilder & sb) const85 void CInterfaceCodeEmitter::EmitLowModeExternalMethod(StringBuilder &sb) const
86 {
87 sb.AppendFormat(
88 "inline struct %s *%sGet(const char *serviceName)\n", interfaceName_.c_str(), interfaceName_.c_str());
89 sb.Append("{\n");
90 sb.Append(TAB).AppendFormat(
91 "return (struct %s *)DevSvcManagerClntGetService(serviceName);\n", interfaceName_.c_str());
92 sb.Append("}\n");
93 }
94
EmitInterfaceHeaderFile()95 void CInterfaceCodeEmitter::EmitInterfaceHeaderFile()
96 {
97 std::string filePath =
98 File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(interfaceName_).c_str()));
99 File file(filePath, File::WRITE);
100 StringBuilder sb;
101
102 EmitLicense(sb);
103 EmitHeadMacro(sb, interfaceFullName_);
104 sb.Append("\n");
105 EmitImportInclusions(sb);
106 sb.Append("\n");
107 EmitHeadExternC(sb);
108 if (!Options::GetInstance().DoPassthrough()) {
109 sb.Append("\n");
110 EmitPreDeclaration(sb);
111 }
112 sb.Append("\n");
113 EmitInterfaceDesc(sb);
114 sb.Append("\n");
115 EmitInterfaceVersionMacro(sb);
116 if (!Options::GetInstance().DoPassthrough()) {
117 sb.Append("\n");
118 EmitInterfaceBuffSizeMacro(sb);
119 sb.Append("\n");
120 EmitInterfaceMethodCommands(sb, "");
121 }
122 sb.Append("\n");
123 EmitInterfaceDefinition(sb);
124 EmitExternalMethod(sb);
125 EmitTailExternC(sb);
126 sb.Append("\n");
127 EmitTailMacro(sb, interfaceFullName_);
128
129 std::string data = sb.ToString();
130 file.WriteData(data.c_str(), data.size());
131 file.Flush();
132 file.Close();
133 }
134
EmitImportInclusions(StringBuilder & sb)135 void CInterfaceCodeEmitter::EmitImportInclusions(StringBuilder &sb)
136 {
137 HeaderFile::HeaderFileSet headerFiles;
138
139 GetStdlibInclusions(headerFiles);
140 GetImportInclusions(headerFiles);
141 GetHeaderOtherLibInclusions(headerFiles);
142
143 for (const auto &file : headerFiles) {
144 sb.AppendFormat("%s\n", file.ToString().c_str());
145 }
146 }
147
GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles) const148 void CInterfaceCodeEmitter::GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const
149 {
150 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
151 if (!Options::GetInstance().DoGenerateKernelCode()) {
152 headerFiles.emplace(HeaderFileType::C_STD_HEADER_FILE, "stdint");
153 headerFiles.emplace(HeaderFileType::C_STD_HEADER_FILE, "stdbool");
154 }
155 }
156
EmitPreDeclaration(StringBuilder & sb) const157 void CInterfaceCodeEmitter::EmitPreDeclaration(StringBuilder &sb) const
158 {
159 sb.Append("struct HdfRemoteService;\n");
160 }
161
EmitInterfaceDesc(StringBuilder & sb) const162 void CInterfaceCodeEmitter::EmitInterfaceDesc(StringBuilder &sb) const
163 {
164 sb.AppendFormat("#define %s \"%s\"\n", interface_->EmitDescMacroName().c_str(), interfaceFullName_.c_str());
165 }
166
EmitInterfaceVersionMacro(StringBuilder & sb) const167 void CInterfaceCodeEmitter::EmitInterfaceVersionMacro(StringBuilder &sb) const
168 {
169 sb.AppendFormat("#define %s %u\n", majorVerName_.c_str(), ast_->GetMajorVer());
170 sb.AppendFormat("#define %s %u\n", minorVerName_.c_str(), ast_->GetMinorVer());
171 }
172
EmitInterfaceDefinition(StringBuilder & sb)173 void CInterfaceCodeEmitter::EmitInterfaceDefinition(StringBuilder &sb)
174 {
175 sb.AppendFormat("struct %s {\n", interfaceName_.c_str());
176 if (mode_ == GenMode::LOW && !interface_->IsSerializable()) {
177 sb.Append(TAB).Append("struct HdfRemoteService *service;\n\n");
178 }
179 EmitInterfaceMethods(sb, TAB);
180 sb.Append("};\n");
181 }
182
EmitInterfaceMethods(StringBuilder & sb,const std::string & prefix) const183 void CInterfaceCodeEmitter::EmitInterfaceMethods(StringBuilder &sb, const std::string &prefix) const
184 {
185 for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
186 EmitInterfaceMethod(method, sb, prefix);
187 sb.Append("\n");
188 }
189
190 EmitInterfaceMethod(interface_->GetVersionMethod(), sb, prefix);
191 if (mode_ == GenMode::IPC) {
192 sb.Append("\n");
193 EmitAsObjectMethod(sb, TAB);
194 }
195 }
196
EmitInterfaceMethod(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const197 void CInterfaceCodeEmitter::EmitInterfaceMethod(
198 const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
199 {
200 if (method->GetParameterNumber() == 0) {
201 sb.Append(prefix).AppendFormat(
202 "int32_t (*%s)(struct %s *self);\n", method->GetName().c_str(), interfaceName_.c_str());
203 } else {
204 StringBuilder paramStr;
205 paramStr.Append(prefix).AppendFormat(
206 "int32_t (*%s)(struct %s *self, ", method->GetName().c_str(), interfaceName_.c_str());
207 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
208 AutoPtr<ASTParameter> param = method->GetParameter(i);
209 EmitInterfaceMethodParameter(param, paramStr, "");
210 if (i + 1 < method->GetParameterNumber()) {
211 paramStr.Append(", ");
212 }
213 }
214
215 paramStr.Append(");");
216 sb.Append(SpecificationParam(paramStr, prefix + TAB));
217 sb.Append("\n");
218 }
219 }
220
EmitAsObjectMethod(StringBuilder & sb,const std::string & prefix) const221 void CInterfaceCodeEmitter::EmitAsObjectMethod(StringBuilder &sb, const std::string &prefix) const
222 {
223 sb.Append(prefix).AppendFormat("struct HdfRemoteService* (*AsObject)(struct %s *self);\n", interfaceName_.c_str());
224 }
225
EmitExternalMethod(StringBuilder & sb) const226 void CInterfaceCodeEmitter::EmitExternalMethod(StringBuilder &sb) const
227 {
228 if (Options::GetInstance().DoPassthrough() && interface_->IsSerializable()) {
229 return;
230 }
231
232 sb.Append("\n");
233 EmitInterfaceGetMethodDecl(sb);
234 sb.Append("\n");
235 EmitInterfaceReleaseMethodDecl(sb);
236 }
237
EmitInterfaceGetMethodDecl(StringBuilder & sb) const238 void CInterfaceCodeEmitter::EmitInterfaceGetMethodDecl(StringBuilder &sb) const
239 {
240 if (mode_ == GenMode::KERNEL) {
241 sb.AppendFormat("struct %s *%sGet(void);\n", interfaceName_.c_str(), interfaceName_.c_str());
242 sb.Append("\n");
243 sb.AppendFormat(
244 "struct %s *%sGetInstance(const char *instanceName);\n", interfaceName_.c_str(), interfaceName_.c_str());
245 return;
246 }
247
248 if (interface_->IsSerializable()) {
249 sb.Append("// no external method used to create client object, it only support ipc mode\n");
250 sb.AppendFormat("struct %s *%sGet(struct HdfRemoteService *remote);\n", interfaceName_.c_str(),
251 interfaceName_.c_str());
252 } else {
253 sb.Append("// external method used to create client object, it support ipc and passthrought mode\n");
254 sb.AppendFormat("struct %s *%sGet(bool isStub);\n", interfaceName_.c_str(), interfaceName_.c_str());
255 sb.AppendFormat("struct %s *%sGetInstance(const char *serviceName, bool isStub);\n", interfaceName_.c_str(),
256 interfaceName_.c_str());
257 }
258 }
259
EmitInterfaceReleaseMethodDecl(StringBuilder & sb) const260 void CInterfaceCodeEmitter::EmitInterfaceReleaseMethodDecl(StringBuilder &sb) const
261 {
262 if (mode_ == GenMode::KERNEL) {
263 sb.AppendFormat("void %sRelease(struct %s *instance);\n", interfaceName_.c_str(), interfaceName_.c_str());
264 return;
265 }
266
267 if (interface_->IsCallback()) {
268 sb.Append("// external method used to release client object, it support ipc and passthrought mode\n");
269 sb.AppendFormat("void %sRelease(struct %s *instance);\n", interfaceName_.c_str(),
270 interfaceName_.c_str());
271 } else if (interface_->IsSerializable()) {
272 sb.Append("// external method used to release client object, it support ipc and passthrought mode\n");
273 sb.AppendFormat("void %sRelease(struct %s *instance, bool isStub);\n", interfaceName_.c_str(),
274 interfaceName_.c_str());
275 } else {
276 sb.Append("// external method used to create release object, it support ipc and passthrought mode\n");
277 sb.AppendFormat("void %sRelease(struct %s *instance, bool isStub);\n", interfaceName_.c_str(),
278 interfaceName_.c_str());
279 sb.AppendFormat("void %sReleaseInstance(const char *serviceName, struct %s *instance, bool isStub);\n",
280 interfaceName_.c_str(), interfaceName_.c_str());
281 }
282 }
283 } // namespace HDI
284 } // namespace OHOS