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/code_emitter.h"
10 #include <cctype>
11 #include "util/file.h"
12 #include "util/options.h"
13
14 namespace OHOS {
15 namespace HDI {
OutPut(const AutoPtr<AST> & ast,const String & targetDirectory,bool isKernelCode)16 bool CodeEmitter::OutPut(const AutoPtr<AST>& ast, const String& targetDirectory, bool isKernelCode)
17 {
18 if (!Reset(ast, targetDirectory, isKernelCode)) {
19 return false;
20 }
21
22 EmitCode();
23 return true;
24 }
25
Reset(const AutoPtr<AST> & ast,const String & targetDirectory,bool isKernelCode)26 bool CodeEmitter::Reset(const AutoPtr<AST>& ast, const String& targetDirectory, bool isKernelCode)
27 {
28 if (ast == nullptr || targetDirectory.Equals("")) {
29 return false;
30 }
31
32 CleanData();
33
34 isKernelCode_ = isKernelCode;
35 ast_ = ast;
36 if (ast_->GetASTFileType() == ASTFileType::AST_IFACE || ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) {
37 interface_ = ast_->GetInterfaceDef();
38 interfaceName_ = interface_->GetName();
39 interfaceFullName_ = interface_->GetNamespace()->ToString() + interfaceName_;
40 baseName_ = interfaceName_.StartsWith("I") ? interfaceName_.Substring(1) : interfaceName_;
41 proxyName_ = baseName_ + "Proxy";
42 proxyFullName_ = interface_->GetNamespace()->ToString() + proxyName_;
43
44 stubName_ = baseName_ + "Stub";
45 stubFullName_ = interface_->GetNamespace()->ToString() + stubName_;
46
47 implName_ = baseName_ + "Service";
48 implFullName_ = interface_->GetNamespace()->ToString() + implName_;
49 } else if (ast_->GetASTFileType() == ASTFileType::AST_TYPES) {
50 baseName_ = ast_->GetName();
51 }
52
53 majorVerName_ = String::Format("%s_MAJOR_VERSION", ConstantName(interfaceName_).string());
54 minorVerName_ = String::Format("%s_MINOR_VERSION", ConstantName(interfaceName_).string());
55 bufferSizeMacroName_ = String::Format("%s_BUFF_MAX_SIZE", ConstantName(baseName_).string());
56
57 String prefix = String::Format("%c%s", tolower(baseName_[0]), baseName_.Substring(1).string());
58 dataParcelName_ = prefix + "Data";
59 replyParcelName_ = prefix + "Reply";
60 optionName_ = prefix + "Option";
61 errorCodeName_ = prefix + "Ret";
62
63 if (!ResolveDirectory(targetDirectory)) {
64 return false;
65 }
66
67 return true;
68 }
69
CleanData()70 void CodeEmitter::CleanData()
71 {
72 isKernelCode_ = false;
73 ast_ = nullptr;
74 interface_ = nullptr;
75 directory_ = "";
76 interfaceName_ = "";
77 interfaceFullName_ = "";
78 baseName_ = "";
79 proxyName_ = "";
80 proxyFullName_ = "";
81 stubName_ = "";
82 stubFullName_ = "";
83 implName_ = "";
84 implFullName_ = "";
85 dataParcelName_ = "";
86 replyParcelName_ = "";
87 optionName_ = "";
88 errorCodeName_ = "";
89 }
90
GetFilePath(const String & outDir)91 String CodeEmitter::GetFilePath(const String& outDir)
92 {
93 String outPath = outDir.EndsWith(File::pathSeparator) ?
94 outDir.Substring(0, outDir.GetLength() - 1) : outDir;
95 String packagePath = Options::GetInstance().GetPackagePath(ast_->GetPackageName());
96 if (packagePath.EndsWith(File::pathSeparator)) {
97 return String::Format("%s/%s", outPath.string(), packagePath.string());
98 } else {
99 return String::Format("%s/%s/", outPath.string(), packagePath.string());
100 }
101 }
102
PackageToFilePath(const String & packageName)103 String CodeEmitter::PackageToFilePath(const String& packageName)
104 {
105 std::vector<String> packageVec = Options::GetInstance().GetSubPackage(packageName).Split(".");
106 StringBuilder filePath;
107 for (auto iter = packageVec.begin(); iter != packageVec.end(); iter++) {
108 filePath.Append(FileName(*iter));
109 if (iter != packageVec.end() - 1) {
110 filePath.Append("/");
111 }
112 }
113
114 return filePath.ToString();
115 }
116
EmitMethodCmdID(const AutoPtr<ASTMethod> & method)117 String CodeEmitter::EmitMethodCmdID(const AutoPtr<ASTMethod>& method)
118 {
119 return String::Format("CMD_%s_%s", ConstantName(baseName_).string(),
120 ConstantName(method->GetName()).string());
121 }
122
EmitInterfaceMethodCommands(StringBuilder & sb,const String & prefix)123 void CodeEmitter::EmitInterfaceMethodCommands(StringBuilder& sb, const String& prefix)
124 {
125 sb.Append(prefix).AppendFormat("enum {\n");
126 for (size_t i = 0; i < interface_->GetMethodNumber(); i++) {
127 AutoPtr<ASTMethod> method = interface_->GetMethod(i);
128 sb.Append(prefix + g_tab).Append(EmitMethodCmdID(method)).Append(",\n");
129 }
130
131 sb.Append(prefix + g_tab).Append(EmitMethodCmdID(interface_->GetVersionMethod())).Append(",\n");
132 sb.Append(prefix).Append("};\n");
133 }
134
EmitVersionHeaderName(const String & name)135 String CodeEmitter::EmitVersionHeaderName(const String& name)
136 {
137 return String::Format("v%u_%u/%s", ast_->GetMajorVer(), ast_->GetMinorVer(), FileName(name).string());
138 }
139
ConstantName(const String & name)140 String CodeEmitter::ConstantName(const String& name)
141 {
142 if (name.IsEmpty()) {
143 return name;
144 }
145
146 StringBuilder sb;
147
148 for (int i = 0; i < name.GetLength(); i++) {
149 char c = name[i];
150 if (isupper(c) != 0) {
151 if (i > 1) {
152 sb.Append('_');
153 }
154 sb.Append(c);
155 } else {
156 sb.Append(toupper(c));
157 }
158 }
159
160 return sb.ToString();
161 }
162
PascalName(const String & name)163 String CodeEmitter::PascalName(const String& name)
164 {
165 if (name.IsEmpty()) {
166 return name;
167 }
168
169 StringBuilder sb;
170 for (int i = 0; i < name.GetLength(); i++) {
171 char c = name[i];
172 if (i == 0) {
173 if (islower(c)) {
174 c = toupper(c);
175 }
176 sb.Append(c);
177 } else {
178 if (c == '_') {
179 continue;
180 }
181
182 if (islower(c) && name[i - 1] == '_') {
183 c = toupper(c);
184 }
185 sb.Append(c);
186 }
187 }
188
189 return sb.ToString();
190 }
191
FileName(const String & name)192 String CodeEmitter::FileName(const String& name)
193 {
194 if (name.IsEmpty()) {
195 return name;
196 }
197
198 StringBuilder sb;
199 for (int i = 0; i < name.GetLength(); i++) {
200 char c = name[i];
201 if (isupper(c) != 0) {
202 // 2->Index of the last char array.
203 if (i > 1) {
204 sb.Append('_');
205 }
206 sb.Append(tolower(c));
207 } else {
208 sb.Append(c);
209 }
210 }
211
212 return sb.ToString();
213 }
214
EmitInterfaceBuffSizeMacro(StringBuilder & sb)215 void CodeEmitter::EmitInterfaceBuffSizeMacro(StringBuilder &sb)
216 {
217 sb.AppendFormat("#ifndef %s\n", MAX_BUFF_SIZE_MACRO);
218 sb.AppendFormat("#define %s (%s)\n", MAX_BUFF_SIZE_MACRO, MAX_BUFF_SIZE_VALUE);
219 sb.Append("#endif\n\n");
220
221 sb.AppendFormat("#ifndef %s\n", CHECK_VALUE_RETURN_MACRO);
222 sb.AppendFormat("#define %s(lv, compare, rv, ret) do { \\\n", CHECK_VALUE_RETURN_MACRO);
223 sb.Append(g_tab).Append("if ((lv) compare (rv)) { \\\n");
224 sb.Append(g_tab).Append(g_tab).Append("return ret; \\\n");
225 sb.Append(g_tab).Append("} \\\n");
226 sb.Append("} while (false)\n");
227 sb.Append("#endif\n\n");
228
229 sb.AppendFormat("#ifndef %s\n", CHECK_VALUE_RET_GOTO_MACRO);
230 sb.AppendFormat("#define %s(lv, compare, rv, ret, value, table) do { \\\n", CHECK_VALUE_RET_GOTO_MACRO);
231 sb.Append(g_tab).Append("if ((lv) compare (rv)) { \\\n");
232 sb.Append(g_tab).Append(g_tab).Append("ret = value; \\\n");
233 sb.Append(g_tab).Append(g_tab).Append("goto table; \\\n");
234 sb.Append(g_tab).Append("} \\\n");
235 sb.Append("} while (false)\n");
236 sb.Append("#endif\n");
237 }
238 } // namespace HDI
239 } // namespace OHOS