1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "codegen/code_emitter.h"
17
18 #include <cctype>
19
20 #include "util/file.h"
21 #include "util/options.h"
22
23 namespace OHOS {
24 namespace Idl {
EmitLicense(StringBuilder & sb)25 void CodeEmitter::EmitLicense(StringBuilder &sb)
26 {
27 if (ast_->GetLicense().empty()) {
28 return;
29 }
30 sb.Append(ast_->GetLicense()).Append("\n\n");
31 }
32
NeedFlag(const AutoPtr<ASTMethod> & method) const33 bool CodeEmitter::NeedFlag(const AutoPtr<ASTMethod> &method) const
34 {
35 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
36 AutoPtr<ASTParameter> param = method->GetParameter(i);
37 if (param == nullptr) {
38 return false;
39 }
40 AutoPtr<ASTType> type = param->GetType();
41 if ((param->GetAttribute() & ASTParamAttr::PARAM_OUT) &&
42 (type->IsStringType() || type->IsArrayType() || type->IsListType())) {
43 return true;
44 }
45 }
46 return false;
47 }
48
49 /*
50 * -r option: -r ohos.hdi:./drivers/interface
51 * outDir: ./out
52 * package: ohos.hdi.foo.v1_0
53 * subPackage: foo.v1_0
54 * subPath: foo/v1_0
55 * GenPath: ./out/foo/v1_0/
56 */
GetFileParentPath(const std::string & outDir) const57 std::string CodeEmitter::GetFileParentPath(const std::string &outDir) const
58 {
59 if (outDir.size() > SIZE_MAX) {
60 return std::string("");
61 }
62 std::string outPath = StringHelper::EndWith(outDir, SEPARATOR) ? outDir.substr(0, outDir.size() - 1) : outDir;
63 std::string subPackage = Options::GetInstance().GetSubPackage(ast_->GetPackageName());
64 std::string subPath = StringHelper::Replace(subPackage, '.', SEPARATOR);
65 if (subPath.empty()) {
66 return File::AdapterPath(StringHelper::Format("%s/", outPath.c_str(), subPath.c_str()));
67 } else {
68 return File::AdapterPath(StringHelper::Format("%s/%s/", outPath.c_str(), subPath.c_str()));
69 }
70 }
71
PackageToFilePath(const std::string & packageName) const72 std::string CodeEmitter::PackageToFilePath(const std::string &packageName) const
73 {
74 std::vector<std::string> packageVec = StringHelper::Split(Options::GetInstance().GetSubPackage(packageName), ".");
75 StringBuilder filePath;
76 for (auto iter = packageVec.begin(); iter != packageVec.end(); iter++) {
77 filePath.Append(FileName(*iter));
78 if (iter != packageVec.end() - 1) {
79 filePath.Append(SEPARATOR);
80 }
81 }
82
83 return filePath.ToString();
84 }
85
InterfaceToFilePath(const std::string & interfaceName) const86 std::string CodeEmitter::InterfaceToFilePath(const std::string &interfaceName) const
87 {
88 std::string fullName = interfaceName;
89 size_t index;
90 if (StringHelper::EndWith(fullName, "]")) {
91 index = fullName.find("[");
92 fullName = fullName.substr(0, index);
93 }
94
95 index = fullName.rfind(".");
96 std::string prefix = fullName.substr(0, index + 1);
97 std::string suffix = fullName.substr(index + 1);
98 std::string fileName = prefix + (StringHelper::StartWith(suffix, "I") ? suffix.substr(1) : suffix) + "Proxy";
99 return PackageToFilePath(fileName);
100 }
101
EmitMethodCmdID(const AutoPtr<ASTMethod> & method)102 std::string CodeEmitter::EmitMethodCmdID(const AutoPtr<ASTMethod> &method)
103 {
104 return StringHelper::Format("CMD_%s_%s%s",
105 ConstantName(baseName_).c_str(), ConstantName(method->GetName()).c_str(),
106 method->GetMethodIdentifier().c_str());
107 }
108
EmitInterfaceMethodCommands(StringBuilder & sb,const std::string & prefix)109 void CodeEmitter::EmitInterfaceMethodCommands(StringBuilder &sb, const std::string &prefix)
110 {
111 sb.Append(prefix).AppendFormat("enum {\n");
112 sb.Append(prefix + TAB).Append(EmitMethodCmdID(interface_->GetVersionMethod())).Append(" = 0,\n");
113 int i = 0;
114 for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
115 sb.Append(prefix + TAB).Append(EmitMethodCmdID(method)).AppendFormat(" = %d", i + 1).Append(",\n");
116 i++;
117 }
118 sb.Append(prefix).Append("};\n");
119 }
120
EmitVersionHeaderName(const std::string & name) const121 std::string CodeEmitter::EmitVersionHeaderName(const std::string &name) const
122 {
123 return StringHelper::Format("v%u_%u/%s", ast_->GetMajorVer(), ast_->GetMinorVer(), FileName(name).c_str());
124 }
125
EmitLogTagMacro(StringBuilder & sb,const std::string & name) const126 void CodeEmitter::EmitLogTagMacro(StringBuilder &sb, const std::string &name) const
127 {
128 sb.AppendFormat("#define HDF_LOG_TAG %s\n", name.c_str());
129 }
130
ConstantName(const std::string & name) const131 std::string CodeEmitter::ConstantName(const std::string &name) const
132 {
133 StringBuilder sb;
134
135 if (name.empty()) {
136 return name;
137 }
138
139 for (size_t i = 0; i < name.size(); i++) {
140 char c = name[i];
141 if (isupper(c) != 0) {
142 if (i > 1) {
143 sb.Append('_');
144 }
145 sb.Append(c);
146 } else {
147 sb.Append(toupper(c));
148 }
149 }
150
151 return sb.ToString();
152 }
153
PascalName(const std::string & name) const154 std::string CodeEmitter::PascalName(const std::string &name) const
155 {
156 if (name.empty()) {
157 return name;
158 }
159
160 StringBuilder sb;
161 for (size_t i = 0; i < name.size(); i++) {
162 char c = name[i];
163 if (i == 0) {
164 if (islower(c)) {
165 c = toupper(c);
166 }
167 sb.Append(c);
168 } else {
169 if (c == '_') {
170 continue;
171 }
172
173 if (islower(c) && name[i - 1] == '_') {
174 c = toupper(c);
175 }
176 sb.Append(c);
177 }
178 }
179
180 return sb.ToString();
181 }
182
FileName(const std::string & name) const183 std::string CodeEmitter::FileName(const std::string &name) const
184 {
185 if (name.empty()) {
186 return name;
187 }
188
189 StringBuilder sb;
190 for (size_t i = 0; i < name.size(); i++) {
191 char c = name[i];
192 if (isupper(c) != 0) {
193 // 2->Index of the last char array.
194 if ((i > 1) && (name[i - 1] != '.') && (name[i - 2] != '.')) {
195 sb.Append('_');
196 }
197 sb.Append(tolower(c));
198 } else {
199 sb.Append(c);
200 }
201 }
202
203 return StringHelper::Replace(sb.ToString(), '.', '/');
204 }
205
GetNamespace(const std::string & fpnp) const206 std::string CodeEmitter::GetNamespace(const std::string &fpnp) const
207 {
208 size_t pos = fpnp.find("..");
209 if (pos == std::string::npos) {
210 return fpnp;
211 }
212
213 return fpnp.substr(pos + strlen(".."));
214 }
215
EmitHeadMacro(StringBuilder & sb,const std::string & fullName) const216 void CodeEmitter::EmitHeadMacro(StringBuilder &sb, const std::string &fullName) const
217 {
218 std::string macroName = MacroName(fullName);
219 sb.Append("#ifndef ").Append(macroName).Append("\n");
220 sb.Append("#define ").Append(macroName).Append("\n");
221 }
222
EmitTailMacro(StringBuilder & sb,const std::string & fullName) const223 void CodeEmitter::EmitTailMacro(StringBuilder &sb, const std::string &fullName) const
224 {
225 std::string macroName = MacroName(fullName);
226 sb.Append("#endif // ").Append(macroName.c_str()).Append("\n\n");
227 }
228
EmitHeadExternC(StringBuilder & sb) const229 void CodeEmitter::EmitHeadExternC(StringBuilder &sb) const
230 {
231 sb.Append("#ifdef __cplusplus\n");
232 sb.Append("extern \"C\" {\n");
233 sb.Append("#endif /* __cplusplus */\n");
234 }
235
EmitTailExternC(StringBuilder & sb) const236 void CodeEmitter::EmitTailExternC(StringBuilder &sb) const
237 {
238 sb.Append("#ifdef __cplusplus\n");
239 sb.Append("}\n");
240 sb.Append("#endif /* __cplusplus */\n");
241 }
242
MacroName(const std::string & name) const243 std::string CodeEmitter::MacroName(const std::string &name) const
244 {
245 if (name.empty()) {
246 return name;
247 }
248
249 std::string macro = StringHelper::StrToUpper(StringHelper::Replace(name, '.', '_')) + "_H";
250 return macro;
251 }
252 } // namespace Idl
253 } // namespace OHOS
254