• 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_service_impl_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 CServiceImplCodeEmitter::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("CServiceImplCodeEmitter", "Create '%s' failed!", directory_.c_str());
25         return false;
26     }
27 
28     return true;
29 }
30 
EmitCode()31 void CServiceImplCodeEmitter::EmitCode()
32 {
33     switch (mode_) {
34         case GenMode::LOW: {
35             EmitLowServiceImplHeaderFile();
36             EmitLowServiceImplSourceFile();
37             break;
38         }
39         case GenMode::PASSTHROUGH:
40         case GenMode::IPC: {
41             if (interface_->IsSerializable()) {
42                 EmitServiceImplHeaderFile();
43             }
44             EmitServiceImplSourceFile();
45             break;
46         }
47         case GenMode::KERNEL: {
48             EmitServiceImplHeaderFile();
49             EmitServiceImplSourceFile();
50             break;
51         }
52         default:
53             break;
54     }
55 }
56 
EmitLowServiceImplHeaderFile()57 void CServiceImplCodeEmitter::EmitLowServiceImplHeaderFile()
58 {
59     std::string filePath =
60         File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(implName_).c_str()));
61     File file(filePath, File::WRITE);
62     StringBuilder sb;
63 
64     sb.Append("\n");
65     EmitLicense(sb);
66     EmitHeadMacro(sb, implFullName_);
67     EmitLowServiceImplInclusions(sb);
68     sb.Append("\n");
69     EmitHeadExternC(sb);
70     sb.Append("\n");
71     EmitLowServiceImplDefinition(sb);
72     sb.Append("\n");
73     EmitServiceImplExternalMethodsDecl(sb);
74     sb.Append("\n");
75     EmitTailExternC(sb);
76     sb.Append("\n");
77     EmitTailMacro(sb, implFullName_);
78 
79     std::string data = sb.ToString();
80     file.WriteData(data.c_str(), data.size());
81     file.Flush();
82     file.Close();
83 }
84 
EmitLowServiceImplInclusions(StringBuilder & sb)85 void CServiceImplCodeEmitter::EmitLowServiceImplInclusions(StringBuilder &sb)
86 {
87     HeaderFile::HeaderFileSet headerFiles;
88     headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
89     for (const auto &file : headerFiles) {
90         sb.AppendFormat("%s\n", file.ToString().c_str());
91     }
92 }
93 
EmitLowServiceImplDefinition(StringBuilder & sb)94 void CServiceImplCodeEmitter::EmitLowServiceImplDefinition(StringBuilder &sb)
95 {
96     sb.AppendFormat("struct %s {\n", implName_.c_str());
97     sb.Append(TAB).AppendFormat("struct %s super;\n", interfaceName_.c_str());
98     sb.Append(TAB).Append("// please add private data here\n");
99     sb.Append("};\n");
100 }
101 
EmitLowServiceImplSourceFile()102 void CServiceImplCodeEmitter::EmitLowServiceImplSourceFile()
103 {
104     std::string filePath =
105         File::AdapterPath(StringHelper::Format("%s/%s.c", directory_.c_str(), FileName(implName_).c_str()));
106     File file(filePath, File::WRITE);
107     StringBuilder sb;
108 
109     EmitLicense(sb);
110     EmitServiceImplSourceInclusions(sb);
111     sb.Append("\n");
112     EmitLogTagMacro(sb, FileName(implName_));
113     sb.Append("\n");
114     EmitServiceImplMethodImpls(sb, "");
115     sb.Append("\n");
116     EmitLowServiceImplGetMethod(sb);
117     sb.Append("\n");
118     EmitServiceImplReleaseMethod(sb);
119 
120     std::string data = sb.ToString();
121     file.WriteData(data.c_str(), data.size());
122     file.Flush();
123     file.Close();
124 }
125 
EmitLowServiceImplGetMethod(StringBuilder & sb)126 void CServiceImplCodeEmitter::EmitLowServiceImplGetMethod(StringBuilder &sb)
127 {
128     sb.AppendFormat("struct %s *%sServiceGet(void)\n", implName_.c_str(), baseName_.c_str());
129     sb.Append("{\n");
130 
131     sb.Append(TAB).AppendFormat("struct %s *service = (struct %s *)OsalMemCalloc(sizeof(struct %s));\n",
132         implName_.c_str(), implName_.c_str(), implName_.c_str());
133     sb.Append(TAB).Append("if (service == NULL) {\n");
134     sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%s: failed to malloc service object\", __func__);\n");
135     sb.Append(TAB).Append("}\n");
136 
137     for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
138         sb.Append(TAB).AppendFormat("service->super.%s = %s%s;\n", method->GetName().c_str(),
139             baseName_.c_str(), method->GetName().c_str());
140     }
141 
142     AutoPtr<ASTMethod> method = interface_->GetVersionMethod();
143     sb.Append(TAB).AppendFormat("service->super.%s = %s%s;\n", method->GetName().c_str(),
144         baseName_.c_str(), method->GetName().c_str());
145 
146     sb.Append(TAB).Append("return service;\n");
147     sb.Append("}\n");
148 }
149 
EmitServiceImplHeaderFile()150 void CServiceImplCodeEmitter::EmitServiceImplHeaderFile()
151 {
152     std::string filePath =
153         File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(baseName_ + "Service").c_str()));
154     File file(filePath, File::WRITE);
155     StringBuilder sb;
156 
157     EmitLicense(sb);
158     EmitHeadMacro(sb, implFullName_);
159     sb.Append("\n");
160     EmitServiceImplHeaderInclusions(sb);
161     sb.Append("\n");
162     EmitHeadExternC(sb);
163     if (mode_ == GenMode::KERNEL) {
164         sb.Append("\n");
165         EmitKernelServiceImplDef(sb);
166     } else if (interface_->IsSerializable()) {
167         sb.Append("\n");
168         EmitServiceImplDef(sb);
169     }
170     sb.Append("\n");
171     EmitServiceImplExternalMethodsDecl(sb);
172     sb.Append("\n");
173     EmitTailExternC(sb);
174     sb.Append("\n");
175     EmitTailMacro(sb, implFullName_);
176 
177     std::string data = sb.ToString();
178     file.WriteData(data.c_str(), data.size());
179     file.Flush();
180     file.Close();
181 }
182 
EmitServiceImplHeaderInclusions(StringBuilder & sb)183 void CServiceImplCodeEmitter::EmitServiceImplHeaderInclusions(StringBuilder &sb)
184 {
185     HeaderFile::HeaderFileSet headerFiles;
186 
187     if (mode_ == GenMode::KERNEL) {
188         headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(stubName_));
189     } else {
190         headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
191     }
192 
193     for (const auto &file : headerFiles) {
194         sb.AppendFormat("%s\n", file.ToString().c_str());
195     }
196 }
197 
EmitServiceImplExternalMethodsDecl(StringBuilder & sb) const198 void CServiceImplCodeEmitter::EmitServiceImplExternalMethodsDecl(StringBuilder &sb) const
199 {
200     std::string instTypeName;
201     if (mode_ == GenMode::LOW || mode_ == GenMode::KERNEL) {
202         instTypeName = implName_;
203     } else {
204         instTypeName = interface_->IsSerializable() ? interfaceName_ : implName_;
205     }
206     sb.AppendFormat("struct %s *%sServiceGet(void);\n\n", instTypeName.c_str(), baseName_.c_str());
207     sb.AppendFormat("void %sServiceRelease(struct %s *instance);\n", baseName_.c_str(), instTypeName.c_str());
208 }
209 
EmitServiceImplSourceFile()210 void CServiceImplCodeEmitter::EmitServiceImplSourceFile()
211 {
212     std::string filePath =
213         File::AdapterPath(StringHelper::Format("%s/%s.c", directory_.c_str(), FileName(implName_).c_str()));
214     File file(filePath, File::WRITE);
215     StringBuilder sb;
216 
217     EmitLicense(sb);
218     EmitServiceImplSourceInclusions(sb);
219     sb.Append("\n");
220     EmitLogTagMacro(sb, FileName(implName_));
221     if (mode_ != GenMode::KERNEL && !interface_->IsSerializable()) {
222         sb.Append("\n");
223         EmitServiceImplDef(sb);
224     }
225 
226     sb.Append("\n");
227     EmitServiceImplMethodImpls(sb, "");
228     if (mode_ == GenMode::KERNEL) {
229         sb.Append("\n");
230         EmitKernelServiceImplGetMethod(sb);
231         sb.Append("\n");
232         EmitKernelServiceImplReleaseMethod(sb);
233     } else {
234         sb.Append("\n");
235         EmitServiceImplGetMethod(sb);
236         sb.Append("\n");
237         EmitServiceImplReleaseMethod(sb);
238     }
239 
240     std::string data = sb.ToString();
241     file.WriteData(data.c_str(), data.size());
242     file.Flush();
243     file.Close();
244 }
245 
EmitServiceImplSourceInclusions(StringBuilder & sb)246 void CServiceImplCodeEmitter::EmitServiceImplSourceInclusions(StringBuilder &sb)
247 {
248     HeaderFile::HeaderFileSet headerFiles;
249 
250     if (mode_ == GenMode::KERNEL || mode_ == GenMode::LOW || interface_->IsSerializable()) {
251         headerFiles.emplace(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(implName_));
252     } else {
253         headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
254     }
255     GetSourceOtherLibInclusions(headerFiles);
256 
257     for (const auto &file : headerFiles) {
258         sb.AppendFormat("%s\n", file.ToString().c_str());
259     }
260 }
261 
GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles) const262 void CServiceImplCodeEmitter::GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const
263 {
264     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
265     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_core_log");
266     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "osal_mem");
267     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec");
268 }
269 
EmitKernelServiceImplDef(StringBuilder & sb) const270 void CServiceImplCodeEmitter::EmitKernelServiceImplDef(StringBuilder &sb) const
271 {
272     sb.AppendFormat("struct %sService {\n", baseName_.c_str());
273     sb.Append(TAB).AppendFormat("struct %sStub stub;\n\n", baseName_.c_str());
274     sb.Append(TAB).Append("// please add private data here\n");
275     sb.Append("};\n");
276 }
277 
EmitServiceImplDef(StringBuilder & sb) const278 void CServiceImplCodeEmitter::EmitServiceImplDef(StringBuilder &sb) const
279 {
280     sb.AppendFormat("struct %sService {\n", baseName_.c_str());
281     sb.Append(TAB).AppendFormat("struct %s interface;\n", interfaceName_.c_str());
282     sb.Append("};\n");
283 }
284 
EmitServiceImplMethodImpls(StringBuilder & sb,const std::string & prefix) const285 void CServiceImplCodeEmitter::EmitServiceImplMethodImpls(StringBuilder &sb, const std::string &prefix) const
286 {
287     for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
288         EmitServiceImplMethodImpl(method, sb, prefix);
289         sb.Append("\n");
290     }
291 
292     EmitServiceImplGetVersionMethod(sb, prefix);
293 }
294 
EmitServiceImplMethodImpl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const295 void CServiceImplCodeEmitter::EmitServiceImplMethodImpl(
296     const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
297 {
298     if (method->GetParameterNumber() == 0) {
299         sb.Append(prefix).AppendFormat("static int32_t %s%s(struct %s *self)\n", baseName_.c_str(),
300             method->GetName().c_str(), interfaceName_.c_str());
301     } else {
302         StringBuilder paramStr;
303         paramStr.Append(prefix).AppendFormat("static int32_t %s%s(struct %s *self, ", baseName_.c_str(),
304             method->GetName().c_str(), interfaceName_.c_str());
305         for (size_t i = 0; i < method->GetParameterNumber(); i++) {
306             AutoPtr<ASTParameter> param = method->GetParameter(i);
307             EmitInterfaceMethodParameter(param, paramStr, "");
308             if (i + 1 < method->GetParameterNumber()) {
309                 paramStr.Append(", ");
310             }
311         }
312 
313         paramStr.Append(")");
314         sb.Append(SpecificationParam(paramStr, prefix + TAB));
315         sb.Append("\n");
316     }
317 
318     sb.Append(prefix).Append("{\n");
319     sb.Append(prefix + TAB).Append("return HDF_SUCCESS;\n");
320     sb.Append(prefix).Append("}\n");
321 }
322 
EmitServiceImplGetVersionMethod(StringBuilder & sb,const std::string & prefix) const323 void CServiceImplCodeEmitter::EmitServiceImplGetVersionMethod(StringBuilder &sb, const std::string &prefix) const
324 {
325     AutoPtr<ASTMethod> method = interface_->GetVersionMethod();
326     sb.Append(prefix).AppendFormat("static int32_t %s%s(struct %s *self, ", baseName_.c_str(),
327         method->GetName().c_str(), interfaceName_.c_str());
328     for (size_t i = 0; i < method->GetParameterNumber(); i++) {
329         AutoPtr<ASTParameter> param = method->GetParameter(i);
330         EmitInterfaceMethodParameter(param, sb, "");
331         if (i + 1 < method->GetParameterNumber()) {
332             sb.Append(", ");
333         }
334     }
335     sb.Append(")\n");
336     sb.Append(prefix).Append("{\n");
337     AutoPtr<ASTParameter> majorParam = method->GetParameter(0);
338     sb.Append(prefix + TAB).AppendFormat("*%s = %s;\n", majorParam->GetName().c_str(), majorVerName_.c_str());
339     AutoPtr<ASTParameter> minorParam = method->GetParameter(1);
340     sb.Append(prefix + TAB).AppendFormat("*%s = %s;\n", minorParam->GetName().c_str(), minorVerName_.c_str());
341     sb.Append(prefix + TAB).Append("return HDF_SUCCESS;\n");
342     sb.Append(prefix).Append("}\n");
343 }
344 
EmitKernelServiceImplGetMethod(StringBuilder & sb) const345 void CServiceImplCodeEmitter::EmitKernelServiceImplGetMethod(StringBuilder &sb) const
346 {
347     std::string objName = "service";
348     sb.AppendFormat("struct %s *%sGet(void)\n", implName_.c_str(), implName_.c_str());
349     sb.Append("{\n");
350     sb.Append(TAB).AppendFormat("struct %s *%s = (struct %s *)OsalMemCalloc(sizeof(struct %s));\n",
351         implName_.c_str(), objName.c_str(), implName_.c_str(), implName_.c_str());
352     sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", objName.c_str());
353     sb.Append(TAB).Append(TAB).AppendFormat(
354         "HDF_LOGE(\"%%{public}s: malloc %s obj failed!\", __func__);\n", implName_.c_str());
355     sb.Append(TAB).Append(TAB).Append("return NULL;\n");
356     sb.Append(TAB).Append("}\n\n");
357     sb.Append(TAB).AppendFormat("if (!%sStubConstruct(&%s->stub)) {\n", baseName_.c_str(), objName.c_str());
358     sb.Append(TAB).Append(TAB).AppendFormat(
359         "HDF_LOGE(\"%%{public}s: construct %sStub obj failed!\", __func__);\n", baseName_.c_str());
360     sb.Append(TAB).Append(TAB).AppendFormat("OsalMemFree(%s);\n", objName.c_str());
361     sb.Append(TAB).Append(TAB).Append("return NULL;\n");
362     sb.Append(TAB).Append("}\n\n");
363 
364     for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
365         sb.Append(TAB).AppendFormat("%s->stub.interface.%s = %s%s;\n", objName.c_str(), method->GetName().c_str(),
366             baseName_.c_str(), method->GetName().c_str());
367     }
368 
369     sb.Append(TAB).AppendFormat("return service;\n", objName.c_str());
370     sb.Append("}\n");
371 }
372 
EmitServiceImplGetMethod(StringBuilder & sb) const373 void CServiceImplCodeEmitter::EmitServiceImplGetMethod(StringBuilder &sb) const
374 {
375     std::string objName = "service";
376     if (interface_->IsSerializable()) {
377         sb.AppendFormat("struct %s *%sServiceGet(void)\n", interfaceName_.c_str(), baseName_.c_str());
378     } else {
379         sb.AppendFormat("struct %s *%sImplGetInstance(void)\n", interfaceName_.c_str(), baseName_.c_str());
380     }
381 
382     sb.Append("{\n");
383     sb.Append(TAB).AppendFormat("struct %s *%s = (struct %s *)OsalMemCalloc(sizeof(struct %s));\n",
384         implName_.c_str(), objName.c_str(), implName_.c_str(), implName_.c_str());
385     sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", objName.c_str());
386     sb.Append(TAB).Append(TAB).AppendFormat(
387         "HDF_LOGE(\"%%{public}s: malloc %s obj failed!\", __func__);\n", implName_.c_str());
388     sb.Append(TAB).Append(TAB).Append("return NULL;\n");
389     sb.Append(TAB).Append("}\n\n");
390     for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
391         sb.Append(TAB).AppendFormat("%s->interface.%s = %s%s;\n", objName.c_str(), method->GetName().c_str(),
392             baseName_.c_str(), method->GetName().c_str());
393     }
394 
395     AutoPtr<ASTMethod> method = interface_->GetVersionMethod();
396     sb.Append(TAB).AppendFormat("%s->interface.%s = %s%s;\n", objName.c_str(), method->GetName().c_str(),
397         baseName_.c_str(), method->GetName().c_str());
398 
399     sb.Append(TAB).AppendFormat("return &%s->interface;\n", objName.c_str());
400     sb.Append("}\n");
401 }
402 
EmitKernelServiceImplReleaseMethod(StringBuilder & sb) const403 void CServiceImplCodeEmitter::EmitKernelServiceImplReleaseMethod(StringBuilder &sb) const
404 {
405     std::string instName = "instance";
406     sb.AppendFormat(
407         "void %sRelease(struct %s *%s)\n", implName_.c_str(), implName_.c_str(), instName.c_str());
408     sb.Append("{\n");
409     sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", instName.c_str());
410     sb.Append(TAB).Append(TAB).Append("return;\n");
411     sb.Append(TAB).Append("}\n\n");
412     sb.Append(TAB).AppendFormat("OsalMemFree(%s);\n", instName.c_str());
413     sb.Append("}\n");
414 }
415 
EmitServiceImplReleaseMethod(StringBuilder & sb) const416 void CServiceImplCodeEmitter::EmitServiceImplReleaseMethod(StringBuilder &sb) const
417 {
418     if (mode_ == GenMode::LOW || mode_ == GenMode::KERNEL) {
419         sb.AppendFormat("void %sRelease(struct %s *instance)\n", implName_.c_str(), implName_.c_str());
420     } else {
421         if (interface_->IsSerializable()) {
422             sb.AppendFormat("void %sServiceRelease(struct %s *instance)\n", baseName_.c_str(), interfaceName_.c_str());
423         } else {
424             sb.AppendFormat("void %sImplRelease(struct %s *instance)\n", baseName_.c_str(), interfaceName_.c_str());
425         }
426     }
427     sb.Append("{\n");
428     sb.Append(TAB).Append("if (instance == NULL) {\n");
429     sb.Append(TAB).Append(TAB).Append("return;\n");
430     sb.Append(TAB).Append("}\n");
431     sb.Append(TAB).Append("OsalMemFree(instance);\n");
432     sb.Append("}\n");
433 }
434 } // namespace HDI
435 } // namespace OHOS