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