• 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/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