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