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