• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include "codegen/c_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