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_service_impl_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 CServiceImplCodeEmitter::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("CServiceImplCodeEmitter", "Create '%s' failed!", directory_.string());
26 return false;
27 }
28
29 return true;
30 }
31
EmitCode()32 void CServiceImplCodeEmitter::EmitCode()
33 {
34 EmitServiceImplHeaderFile();
35 EmitServiceImplSourceFile();
36 }
37
EmitServiceImplHeaderFile()38 void CServiceImplCodeEmitter::EmitServiceImplHeaderFile()
39 {
40 String filePath = String::Format("%s/%s.h", directory_.string(), FileName(baseName_ + "Service").string());
41 File file(filePath, File::WRITE);
42 StringBuilder sb;
43
44 EmitLicense(sb);
45 EmitHeadMacro(sb, implFullName_);
46 sb.Append("\n");
47 EmitServiceImplHeaderInclusions(sb);
48 sb.Append("\n");
49 EmitHeadExternC(sb);
50 if (!interface_->IsSerializable()) {
51 sb.Append("\n");
52 EmitServiceImplDef(sb);
53 }
54 sb.Append("\n");
55 EmitServiceImplConstructDecl(sb);
56 sb.Append("\n");
57 EmitTailExternC(sb);
58 sb.Append("\n");
59 EmitTailMacro(sb, implFullName_);
60
61 String data = sb.ToString();
62 file.WriteData(data.string(), data.GetLength());
63 file.Flush();
64 file.Close();
65 }
66
EmitServiceImplHeaderInclusions(StringBuilder & sb)67 void CServiceImplCodeEmitter::EmitServiceImplHeaderInclusions(StringBuilder& sb)
68 {
69 HeaderFile::HeaderFileSet headerFiles;
70
71 headerFiles.emplace(HeaderFile(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(stubName_)));
72
73 for (const auto& file : headerFiles) {
74 sb.AppendFormat("%s\n", file.ToString().string());
75 }
76 }
77
EmitServiceImplConstructDecl(StringBuilder & sb)78 void CServiceImplCodeEmitter::EmitServiceImplConstructDecl(StringBuilder& sb)
79 {
80 String instTypeName = interface_->IsSerializable() ? interfaceName_ : implName_;
81 sb.AppendFormat("struct %s *%sServiceGet(void);\n\n", instTypeName.string(), baseName_.string());
82 sb.AppendFormat("void %sServiceRelease(struct %s *instance);\n", baseName_.string(), instTypeName.string());
83 }
84
EmitServiceImplSourceFile()85 void CServiceImplCodeEmitter::EmitServiceImplSourceFile()
86 {
87 String filePath = String::Format("%s/%s.c", directory_.string(), FileName(baseName_ + "Service").string());
88 File file(filePath, File::WRITE);
89 StringBuilder sb;
90
91 EmitLicense(sb);
92 EmitServiceImplSourceInclusions(sb);
93 if (interface_->IsSerializable()) {
94 sb.Append("\n");
95 EmitServiceImplDef(sb);
96 }
97
98 sb.Append("\n");
99 EmitServiceImplMethodImpls(sb, "");
100 sb.Append("\n");
101 EmitServiceImplGetMethod(sb);
102 sb.Append("\n");
103 EmitServiceImplReleaseMethod(sb);
104
105 String data = sb.ToString();
106 file.WriteData(data.string(), data.GetLength());
107 file.Flush();
108 file.Close();
109 }
110
EmitServiceImplSourceInclusions(StringBuilder & sb)111 void CServiceImplCodeEmitter::EmitServiceImplSourceInclusions(StringBuilder& sb)
112 {
113 HeaderFile::HeaderFileSet headerFiles;
114
115 headerFiles.emplace(HeaderFile(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(implName_)));
116 GetSourceOtherLibInclusions(headerFiles);
117
118 for (const auto& file : headerFiles) {
119 sb.AppendFormat("%s\n", file.ToString().string());
120 }
121 }
122
GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles)123 void CServiceImplCodeEmitter::GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet& headerFiles)
124 {
125 headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base"));
126 headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_log"));
127 headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "osal_mem"));
128 headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec"));
129 }
130
EmitServiceImplDef(StringBuilder & sb)131 void CServiceImplCodeEmitter::EmitServiceImplDef(StringBuilder& sb)
132 {
133 sb.AppendFormat("struct %sService\n", baseName_.string());
134 sb.Append("{\n");
135 sb.Append(g_tab).AppendFormat("struct %sStub stub;\n\n", baseName_.string());
136 sb.Append(g_tab).Append("// please add private data here\n");
137 sb.Append("};\n");
138 }
139
EmitServiceImplMethodImpls(StringBuilder & sb,const String & prefix)140 void CServiceImplCodeEmitter::EmitServiceImplMethodImpls(StringBuilder& sb, const String& prefix)
141 {
142 for (size_t i = 0; i < interface_->GetMethodNumber(); i++) {
143 AutoPtr<ASTMethod> method = interface_->GetMethod(i);
144 EmitServiceImplMethodImpl(method, sb, prefix);
145 if (i + 1 < interface_->GetMethodNumber()) {
146 sb.Append("\n");
147 }
148 }
149 }
150
EmitServiceImplMethodImpl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const String & prefix)151 void CServiceImplCodeEmitter::EmitServiceImplMethodImpl(const AutoPtr<ASTMethod>& method, StringBuilder& sb,
152 const String& prefix)
153 {
154 if (method->GetParameterNumber() == 0) {
155 sb.Append(prefix).AppendFormat("int32_t %s%s(struct %s *self)\n",
156 baseName_.string(), method->GetName().string(), interfaceName_.string());
157 } else {
158 StringBuilder paramStr;
159 paramStr.Append(prefix).AppendFormat("int32_t %s%s(struct %s *self, ",
160 baseName_.string(), method->GetName().string(), interfaceName_.string());
161 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
162 AutoPtr<ASTParameter> param = method->GetParameter(i);
163 EmitInterfaceMethodParameter(param, paramStr, "");
164 if (i + 1 < method->GetParameterNumber()) {
165 paramStr.Append(", ");
166 }
167 }
168
169 paramStr.Append(")");
170 sb.Append(SpecificationParam(paramStr, prefix + g_tab));
171 sb.Append("\n");
172 }
173
174 sb.Append(prefix).Append("{\n");
175 sb.Append(prefix + g_tab).Append("return HDF_SUCCESS;\n");
176 sb.Append(prefix).Append("}\n");
177 }
178
EmitServiceImplGetMethod(StringBuilder & sb)179 void CServiceImplCodeEmitter::EmitServiceImplGetMethod(StringBuilder& sb)
180 {
181 String implTypeName = String::Format("%sService", baseName_.string());
182 String objName = "service";
183
184 if (!interface_->IsSerializable()) {
185 sb.AppendFormat("struct %s *%sGet(void)\n", implName_.string(), implTypeName.string());
186 } else {
187 sb.AppendFormat("struct %s *%sGet(void)\n", interfaceName_.string(), implTypeName.string());
188 }
189 sb.Append("{\n");
190
191 sb.Append(g_tab).AppendFormat("struct %s *%s = (struct %s *)OsalMemCalloc(sizeof(struct %s));\n",
192 implTypeName.string(), objName.string(), implTypeName.string(), implTypeName.string());
193 sb.Append(g_tab).AppendFormat("if (%s == NULL) {\n", objName.string());
194 sb.Append(g_tab).Append(g_tab).AppendFormat("HDF_LOGE(\"%%{public}s: malloc %s obj failed!\", __func__);\n",
195 implTypeName.string());
196 sb.Append(g_tab).Append(g_tab).Append("return NULL;\n");
197 sb.Append(g_tab).Append("}\n\n");
198
199 sb.Append(g_tab).AppendFormat("if (!%sStubConstruct(&%s->stub)) {\n", baseName_.string(), objName.string());
200 sb.Append(g_tab).Append(g_tab).AppendFormat("HDF_LOGE(\"%%{public}s: construct %sStub obj failed!\", __func__);\n",
201 baseName_.string());
202 sb.Append(g_tab).Append(g_tab).AppendFormat("OsalMemFree(%s);\n", objName.string());
203 sb.Append(g_tab).Append(g_tab).Append("return NULL;\n");
204 sb.Append(g_tab).Append("}\n\n");
205
206 for (size_t i = 0; i < interface_->GetMethodNumber(); i++) {
207 AutoPtr<ASTMethod> method = interface_->GetMethod(i);
208 sb.Append(g_tab).AppendFormat("%s->stub.interface.%s = %s%s;\n", objName.string(), method->GetName().string(),
209 baseName_.string(), method->GetName().string());
210 }
211
212 if (interface_->IsSerializable()) {
213 sb.Append(g_tab).AppendFormat("return &%s->stub.interface;\n", objName.string());
214 } else {
215 sb.Append(g_tab).AppendFormat("return service;\n", objName.string());
216 }
217 sb.Append("}\n");
218 }
219
EmitServiceImplReleaseMethod(StringBuilder & sb)220 void CServiceImplCodeEmitter::EmitServiceImplReleaseMethod(StringBuilder& sb)
221 {
222 String implTypeName = String::Format("%sService", baseName_.string());
223 String instName = "instance";
224 String objName = "service";
225
226 if (interface_->IsSerializable()) {
227 sb.AppendFormat("void %sRelease(struct %s *%s)\n", implTypeName.string(), interfaceName_.string(),
228 instName.string());
229 sb.Append("{\n");
230 sb.Append(g_tab).AppendFormat("struct %s *%s = (struct %s *)%s;\n", implTypeName.string(), objName.string(),
231 implTypeName.string(), instName.string());
232 sb.Append(g_tab).AppendFormat("if (%s == NULL) {\n", objName.string());
233 sb.Append(g_tab).Append(g_tab).Append("return;\n");
234 sb.Append(g_tab).Append("}\n\n");
235 sb.Append(g_tab).AppendFormat("%sStubRelease(&%s->stub);\n", baseName_.string(), objName.string());
236 sb.Append(g_tab).AppendFormat("OsalMemFree(%s);\n", objName.string());
237 } else {
238 sb.AppendFormat("void %sRelease(struct %s *%s)\n", implTypeName.string(), implTypeName.string(),
239 instName.string());
240 sb.Append("{\n");
241 sb.Append(g_tab).AppendFormat("if (%s == NULL) {\n", instName.string());
242 sb.Append(g_tab).Append(g_tab).Append("return;\n");
243 sb.Append(g_tab).Append("}\n\n");
244 sb.Append(g_tab).AppendFormat("OsalMemFree(%s);\n", instName.string());
245 }
246 sb.Append("}\n");
247 }
248 } // namespace HDI
249 } // namespace OHOS