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_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 EmitInterfaceHeaderFile();
34 }
35
EmitInterfaceHeaderFile()36 void CInterfaceCodeEmitter::EmitInterfaceHeaderFile()
37 {
38 std::string filePath =
39 File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(interfaceName_).c_str()));
40 File file(filePath, File::WRITE);
41 StringBuilder sb;
42
43 EmitLicense(sb);
44 EmitHeadMacro(sb, interfaceFullName_);
45 sb.Append("\n");
46 EmitImportInclusions(sb);
47 sb.Append("\n");
48 EmitHeadExternC(sb);
49 if (!Options::GetInstance().DoPassthrough()) {
50 sb.Append("\n");
51 EmitPreDeclaration(sb);
52 }
53 sb.Append("\n");
54 EmitInterfaceDesc(sb);
55 sb.Append("\n");
56 EmitInterfaceVersionMacro(sb);
57 if (!Options::GetInstance().DoPassthrough()) {
58 sb.Append("\n");
59 EmitInterfaceBuffSizeMacro(sb);
60 sb.Append("\n");
61 EmitInterfaceMethodCommands(sb, "");
62 }
63 sb.Append("\n");
64 EmitInterfaceDefinition(sb);
65 EmitExternalMethod(sb);
66 EmitTailExternC(sb);
67 sb.Append("\n");
68 EmitTailMacro(sb, interfaceFullName_);
69
70 std::string data = sb.ToString();
71 file.WriteData(data.c_str(), data.size());
72 file.Flush();
73 file.Close();
74 }
75
EmitImportInclusions(StringBuilder & sb)76 void CInterfaceCodeEmitter::EmitImportInclusions(StringBuilder &sb)
77 {
78 HeaderFile::HeaderFileSet headerFiles;
79
80 GetImportInclusions(headerFiles);
81 GetHeaderOtherLibInclusions(headerFiles);
82
83 for (const auto &file : headerFiles) {
84 sb.AppendFormat("%s\n", file.ToString().c_str());
85 }
86 }
87
GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles)88 void CInterfaceCodeEmitter::GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles)
89 {
90 if (!Options::GetInstance().DoGenerateKernelCode()) {
91 headerFiles.emplace(HeaderFileType::C_STD_HEADER_FILE, "stdint");
92 headerFiles.emplace(HeaderFileType::C_STD_HEADER_FILE, "stdbool");
93 }
94 }
95
EmitPreDeclaration(StringBuilder & sb)96 void CInterfaceCodeEmitter::EmitPreDeclaration(StringBuilder &sb)
97 {
98 sb.Append("struct HdfRemoteService;\n");
99 }
100
EmitInterfaceDesc(StringBuilder & sb)101 void CInterfaceCodeEmitter::EmitInterfaceDesc(StringBuilder &sb)
102 {
103 sb.AppendFormat("#define %s \"%s\"\n", interface_->EmitDescMacroName().c_str(), interfaceFullName_.c_str());
104 }
105
EmitInterfaceVersionMacro(StringBuilder & sb)106 void CInterfaceCodeEmitter::EmitInterfaceVersionMacro(StringBuilder &sb)
107 {
108 sb.AppendFormat("#define %s %u\n", majorVerName_.c_str(), ast_->GetMajorVer());
109 sb.AppendFormat("#define %s %u\n", minorVerName_.c_str(), ast_->GetMinorVer());
110 }
111
EmitInterfaceDefinition(StringBuilder & sb)112 void CInterfaceCodeEmitter::EmitInterfaceDefinition(StringBuilder &sb)
113 {
114 sb.AppendFormat("struct %s {\n", interfaceName_.c_str());
115 EmitInterfaceMethods(sb, TAB);
116 sb.Append("};\n");
117 }
118
EmitInterfaceMethods(StringBuilder & sb,const std::string & prefix)119 void CInterfaceCodeEmitter::EmitInterfaceMethods(StringBuilder &sb, const std::string &prefix)
120 {
121 for (size_t i = 0; i < interface_->GetMethodNumber(); i++) {
122 AutoPtr<ASTMethod> method = interface_->GetMethod(i);
123 EmitInterfaceMethod(method, sb, prefix);
124 sb.Append("\n");
125 }
126
127 EmitInterfaceMethod(interface_->GetVersionMethod(), sb, prefix);
128 if (!isKernelCode_ && !Options::GetInstance().DoPassthrough()) {
129 sb.Append("\n");
130 EmitAsObjectMethod(sb, TAB);
131 }
132 }
133
EmitInterfaceMethod(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix)134 void CInterfaceCodeEmitter::EmitInterfaceMethod(
135 const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix)
136 {
137 if (method->GetParameterNumber() == 0) {
138 sb.Append(prefix).AppendFormat(
139 "int32_t (*%s)(struct %s *self);\n", method->GetName().c_str(), interfaceName_.c_str());
140 } else {
141 StringBuilder paramStr;
142 paramStr.Append(prefix).AppendFormat(
143 "int32_t (*%s)(struct %s *self, ", method->GetName().c_str(), interfaceName_.c_str());
144 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
145 AutoPtr<ASTParameter> param = method->GetParameter(i);
146 EmitInterfaceMethodParameter(param, paramStr, "");
147 if (i + 1 < method->GetParameterNumber()) {
148 paramStr.Append(", ");
149 }
150 }
151
152 paramStr.Append(");");
153 sb.Append(SpecificationParam(paramStr, prefix + TAB));
154 sb.Append("\n");
155 }
156 }
157
EmitAsObjectMethod(StringBuilder & sb,const std::string & prefix)158 void CInterfaceCodeEmitter::EmitAsObjectMethod(StringBuilder &sb, const std::string &prefix)
159 {
160 sb.Append(prefix).AppendFormat("struct HdfRemoteService* (*AsObject)(struct %s *self);\n", interfaceName_.c_str());
161 }
162
EmitExternalMethod(StringBuilder & sb)163 void CInterfaceCodeEmitter::EmitExternalMethod(StringBuilder &sb)
164 {
165 if (Options::GetInstance().DoPassthrough() && interface_->IsSerializable()) {
166 return;
167 }
168
169 sb.Append("\n");
170 EmitInterfaceGetMethodDecl(sb);
171 sb.Append("\n");
172 EmitInterfaceReleaseMethodDecl(sb);
173 }
174
EmitInterfaceGetMethodDecl(StringBuilder & sb)175 void CInterfaceCodeEmitter::EmitInterfaceGetMethodDecl(StringBuilder &sb)
176 {
177 if (isKernelCode_) {
178 sb.AppendFormat("struct %s *%sGet(void);\n", interfaceName_.c_str(), interfaceName_.c_str());
179 sb.Append("\n");
180 sb.AppendFormat(
181 "struct %s *%sGetInstance(const char *instanceName);\n", interfaceName_.c_str(), interfaceName_.c_str());
182 return;
183 }
184
185 if (interface_->IsSerializable()) {
186 sb.Append("// no external method used to create client object, it only support ipc mode\n");
187 sb.AppendFormat("struct %s *%sGet(struct HdfRemoteService *remote);\n", interfaceName_.c_str(),
188 interfaceName_.c_str());
189 } else {
190 sb.Append("// external method used to create client object, it support ipc and passthrought mode\n");
191 sb.AppendFormat("struct %s *%sGet(bool isStub);\n", interfaceName_.c_str(), interfaceName_.c_str());
192 sb.AppendFormat("struct %s *%sGetInstance(const char *serviceName, bool isStub);\n", interfaceName_.c_str(),
193 interfaceName_.c_str());
194 }
195 }
196
EmitInterfaceReleaseMethodDecl(StringBuilder & sb)197 void CInterfaceCodeEmitter::EmitInterfaceReleaseMethodDecl(StringBuilder &sb)
198 {
199 if (isKernelCode_) {
200 sb.AppendFormat("void %sRelease(struct %s *instance);\n", interfaceName_.c_str(), interfaceName_.c_str());
201 return;
202 }
203
204 if (interface_->IsCallback()) {
205 sb.Append("// external method used to release client object, it support ipc and passthrought mode\n");
206 sb.AppendFormat("void %sRelease(struct %s *instance);\n", interfaceName_.c_str(),
207 interfaceName_.c_str());
208 } else if (interface_->IsSerializable()) {
209 sb.Append("// external method used to release client object, it support ipc and passthrought mode\n");
210 sb.AppendFormat("void %sRelease(struct %s *instance, bool isStub);\n", interfaceName_.c_str(),
211 interfaceName_.c_str());
212 } else {
213 sb.Append("// external method used to create release object, it support ipc and passthrought mode\n");
214 sb.AppendFormat("void %sRelease(struct %s *instance, bool isStub);\n", interfaceName_.c_str(),
215 interfaceName_.c_str());
216 sb.AppendFormat("void %sReleaseInstance(const char *serviceName, struct %s *instance, bool isStub);\n",
217 interfaceName_.c_str(), interfaceName_.c_str());
218 }
219 }
220 } // namespace HDI
221 } // namespace OHOS