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 "sa_code_emitter.h"
17 #include "ast/ast_map_type.h"
18 #include "type/sa_boolean_type_emitter.h"
19 #include "type/sa_byte_type_emitter.h"
20 #include "type/sa_short_type_emitter.h"
21 #include "type/sa_int_type_emitter.h"
22 #include "type/sa_long_type_emitter.h"
23 #include "type/sa_float_type_emitter.h"
24 #include "type/sa_double_type_emitter.h"
25 #include "type/sa_char_type_emitter.h"
26 #include "type/sa_string_type_emitter.h"
27 #include "type/sa_seq_type_emitter.h"
28 #include "type/sa_interface_type_emitter.h"
29 #include "type/sa_map_type_emitter.h"
30 #include "type/sa_array_type_emitter.h"
31 
32 #include <cctype>
33 #include <sys/stat.h>
34 #include <unistd.h>
35 #include "util/file.h"
36 #include "util/options.h"
37 #include "util/logger.h"
38 #include "util/string_helper.h"
39 
40 namespace OHOS {
41 namespace Idl {
42 SACodeEmitter::TypeEmitterMap SACodeEmitter::basicEmitters_ = {
43     {TypeKind::TYPE_BOOLEAN,           new SaBooleanTypeEmitter()     },
44     {TypeKind::TYPE_BYTE,              new SaByteTypeEmitter()        },
45     {TypeKind::TYPE_SHORT,             new SaShortTypeEmitter()       },
46     {TypeKind::TYPE_INT,               new SaIntTypeEmitter()         },
47     {TypeKind::TYPE_LONG,              new SaLongTypeEmitter()        },
48     {TypeKind::TYPE_FLOAT,             new SaFloatTypeEmitter()       },
49     {TypeKind::TYPE_DOUBLE,            new SaDoubleTypeEmitter()      },
50     {TypeKind::TYPE_CHAR,              new SaCharTypeEmitter()        },
51     {TypeKind::TYPE_STRING,            new SaStringTypeEmitter()      },
52 };
53 
OutPut(const AutoPtr<AST> & ast,const std::string & targetDirectory,GenMode mode)54 bool SACodeEmitter::OutPut(const AutoPtr<AST> &ast, const std::string &targetDirectory, GenMode mode)
55 {
56     if (!Reset(ast, targetDirectory, mode)) {
57         return false;
58     }
59 
60     EmitCode();
61     return true;
62 }
63 
Reset(const AutoPtr<AST> & ast,const std::string & targetDirectory,GenMode mode)64 bool SACodeEmitter::Reset(const AutoPtr<AST> &ast, const std::string &targetDirectory, GenMode mode)
65 {
66     if ((ast == nullptr) || (ast->GetASTFileType() != ASTFileType::AST_IFACE)) {
67         return false;
68     }
69 
70     CleanData();
71 
72     ast_ = ast;
73     for (auto interface : ast_->GetInterfaceDefs()) {
74         if (interface->IsExternal() == false) {
75             interface_ = interface;
76             break;
77         }
78     }
79     if (interface_ != nullptr) {
80         interfaceName_ = interface_->GetName();
81         interfaceFullName_ = interface_->GetNamespace()->ToString() + interfaceName_;
82         baseName_ = StringHelper::StartWith(interfaceName_, "I") ? interfaceName_.substr(1) : interfaceName_;
83         proxyName_ = baseName_ + "Proxy";
84         proxyFullName_ = interface_->GetNamespace()->ToString() + proxyName_;
85 
86         stubName_ = baseName_ + "Stub";
87         stubFullName_ = interface_->GetNamespace()->ToString() + stubName_;
88         deathRecipientName_ = StringHelper::StartWith(interfaceName_, "I") ? interfaceName_.substr(1) + "Recipient" :
89             interfaceName_ + "Recipient";
90     }
91 
92     if (!ResolveDirectory(targetDirectory)) {
93         return false;
94     }
95 
96     return true;
97 }
98 
CleanData()99 void SACodeEmitter::CleanData()
100 {
101     Options &options = Options::GetInstance();
102 
103     domainId_ = options.GetDomainId();
104     logTag_ = options.GetLogTag();
105     hitraceTag_ = options.GetGenerateHitraceTag();
106     hitraceOn_ = options.DoHitraceState();
107     logOn_ = options.DoLogOn();
108     SaTypeEmitter::logOn_ = logOn_;
109     ast_ = nullptr;
110     interface_ = nullptr;
111     directory_ = "";
112     interfaceName_ = "";
113     interfaceFullName_ = "";
114     baseName_ = "";
115     proxyName_ = "";
116     proxyFullName_ = "";
117     stubName_ = "";
118     stubFullName_ = "";
119 }
120 
ResolveDirectory(const std::string & targetDirectory)121 bool SACodeEmitter::ResolveDirectory(const std::string &targetDirectory)
122 {
123     directory_ = targetDirectory;
124 #ifdef __MINGW32__
125     if (targetDirectory.find(":\\") == std::string::npos) {
126         char* cwd = getcwd(nullptr, 0);
127         directory_ = StringHelper::Format("%s\\%s", cwd, targetDirectory.c_str());
128         free(cwd);
129     }
130 #else
131     if (!StringHelper::StartWith(targetDirectory, "/")) {
132         char* cwd = getcwd(nullptr, 0);
133         directory_ = StringHelper::Format("%s/%s", cwd, targetDirectory.c_str());
134         free(cwd);
135     }
136 #endif
137 
138     if (!access(directory_.c_str(), R_OK | W_OK)) {
139         return true;
140     }
141 
142 #ifdef __MINGW32__
143     if (mkdir(directory_.c_str()) != 0) {
144 #else
145     if (mkdir(directory_.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) != 0) {
146 #endif
147         Logger::E(TAG, "Create \"%s\" directory failed.", directory_.c_str());
148         return false;
149     }
150 
151     return true;
152 }
153 
154 AutoPtr<SaTypeEmitter> SACodeEmitter::GetTypeEmitter(AutoPtr<ASTType> astType) const
155 {
156     AutoPtr<SaTypeEmitter> typeEmitter;
157     auto basicTypePair = basicEmitters_.find(astType->GetTypeKind());
158     if (basicTypePair != basicEmitters_.end()) {
159         typeEmitter = (static_cast<SaTypeEmitter*>(basicTypePair->second.Get()));
160     }
161 
162     if (typeEmitter == nullptr) {
163         typeEmitter = NewTypeEmitter(astType);
164     }
165 
166     typeEmitter->SetTypeName(astType->ToString());
167     return typeEmitter;
168 }
169 
170 AutoPtr<SaTypeEmitter> SACodeEmitter::NewTypeEmitter(AutoPtr<ASTType> astType) const
171 {
172     switch (astType->GetTypeKind()) {
173         case TypeKind::TYPE_MAP:
174             return NewMapTypeEmitter(astType);
175         case TypeKind::TYPE_ARRAY:
176             return NewArrayTypeEmitter(astType);
177         case TypeKind::TYPE_LIST:
178             return NewListTypeEmitter(astType);
179         case TypeKind::TYPE_SEQUENCEABLE:
180             return new SaSeqTypeEmitter();
181         case TypeKind::TYPE_INTERFACE:
182             return new SaInterfaceTypeEmitter();
183         default: {
184             // type not match, new a empty emitter
185             AutoPtr<SaTypeEmitter> typeEmitter = new SaTypeEmitter();
186             return typeEmitter;
187         }
188     }
189 }
190 
191 AutoPtr<SaTypeEmitter> SACodeEmitter::NewMapTypeEmitter(AutoPtr<ASTType> astType) const
192 {
193     AutoPtr<SaMapTypeEmitter> mapTypeEmitter = new SaMapTypeEmitter();
194     AutoPtr<ASTType> keyType = (static_cast<ASTMapType*>(astType.Get()))->GetKeyType();
195     AutoPtr<ASTType> valueType = (static_cast<ASTMapType*>(astType.Get()))->GetValueType();
196     AutoPtr<SaTypeEmitter> keyEmitter = GetTypeEmitter(keyType);
197     AutoPtr<SaTypeEmitter> valueEmitter = GetTypeEmitter(valueType);
198     mapTypeEmitter->SetKeyEmitter(keyEmitter);
199     mapTypeEmitter->SetValueEmitter(valueEmitter);
200     return mapTypeEmitter.Get();
201 }
202 
203 AutoPtr<SaTypeEmitter> SACodeEmitter::NewArrayTypeEmitter(AutoPtr<ASTType> astType) const
204 {
205     AutoPtr<SaArrayTypeEmitter> arrayTypeEmitter = new SaArrayTypeEmitter();
206     AutoPtr<ASTType> elemType = (static_cast<ASTArrayType*>(astType.Get()))->GetElementType();
207     AutoPtr<SaTypeEmitter> elemEmitter = GetTypeEmitter(elemType);
208     arrayTypeEmitter->SetElementEmitter(elemEmitter);
209     return arrayTypeEmitter.Get();
210 }
211 
212 AutoPtr<SaTypeEmitter> SACodeEmitter::NewListTypeEmitter(AutoPtr<ASTType> astType) const
213 {
214     AutoPtr<SaListTypeEmitter> listTypeEmitter = new SaListTypeEmitter();
215     AutoPtr<ASTType> elemType = (static_cast<ASTListType*>(astType.Get()))->GetElementType();
216     AutoPtr<SaTypeEmitter> elemEmitter = GetTypeEmitter(elemType);
217     listTypeEmitter->SetElementEmitter(elemEmitter);
218     return listTypeEmitter.Get();
219 }
220 } // namespace Idl
221 } // namespace OHOS
222