• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2022 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 "assembler/assembly-function.h"
17 #include "libpandafile/literal_data_accessor.h"
18 #include "os/file.h"
19 #include "options.h"
20 
21 #include "mergeProgram.h"
22 
23 #if defined(PANDA_TARGET_WINDOWS)
24 #include <io.h>
25 #else
26 #include <dirent.h>
27 #endif
28 
29 #include <fstream>
30 
31 namespace panda::proto {
32 #if PANDA_TARGET_WINDOWS
EnumerateFilesWindows(const std::string & protoBinPath,const std::string & protoBinSuffix,std::vector<std::string> & directoryFiles)33 bool MergeProgram::EnumerateFilesWindows(const std::string &protoBinPath, const std::string &protoBinSuffix,
34                                          std::vector<std::string> &directoryFiles)
35 {
36     int handle = 0;
37     struct _finddata_t fileInfo;
38     std::string path;
39     if ((handle = _findfirst(path.assign(protoBinPath).append("\\*").c_str(), &fileInfo)) == -1) {
40         return false;
41     }
42     do {
43         if (fileInfo.attrib & _A_SUBDIR) {
44             if ((!strncmp(fileInfo.name, ".", 1)) || (!strncmp(fileInfo.name, "..", 2))) {
45                 continue;
46             }
47             if (!GetProtoFiles(path.assign(protoBinPath).append("\\").append(fileInfo.name), protoBinSuffix,
48                                directoryFiles)) {
49                 _findclose(handle);
50                 return false;
51             }
52         } else {
53             std::string fileName(fileInfo.name);
54             if (fileName.substr(fileName.find_last_of(".") + 1).compare(protoBinSuffix) == 0) {
55                 directoryFiles.emplace_back(path.assign(protoBinPath).append("\\").append(fileName));
56             }
57         }
58     } while (_findnext(handle, &fileInfo) == 0);
59     _findclose(handle);
60     return true;
61 }
62 
63 #elif PANDA_TARGET_UNIX
64 bool MergeProgram::EnumerateFilesUnix(const std::string &protoBinPath, const std::string &protoBinSuffix,
65                                       std::vector<std::string> &directoryFiles)
66 {
67     DIR *protoBin = opendir(protoBinPath.c_str());
68     if (protoBin == nullptr) {
69         return false;
70     }
71     dirent *dir = nullptr;
72     std::string pathPrefix = protoBinPath + "/";
73     while ((dir = readdir(protoBin)) != nullptr) {
74         if ((!strncmp(dir->d_name, ".", 1)) || (!strncmp(dir->d_name, "..", 2))) {
75             continue;
76         }
77         if (dir->d_type == DT_DIR) {
78             std::string subDirName = pathPrefix + dir->d_name;
79             if (!GetProtoFiles(subDirName, protoBinSuffix, directoryFiles)) {
80                 closedir(protoBin);
81                 return false;
82             }
83         } else {
84             std::string fileName = pathPrefix + dir->d_name;
85             if (fileName.substr(fileName.find_last_of(".") + 1).compare(protoBinSuffix) == 0) {
86                 directoryFiles.emplace_back(fileName);
87             }
88         }
89     }
90     closedir(protoBin);
91     return true;
92 }
93 #endif
94 
GetProtoFiles(const std::string & protoBinPath,const std::string & protoBinSuffix,std::vector<std::string> & directoryFiles)95 bool MergeProgram::GetProtoFiles(const std::string &protoBinPath, const std::string &protoBinSuffix,
96                                  std::vector<std::string> &directoryFiles)
97 {
98 #if PANDA_TARGET_WINDOWS
99     return EnumerateFilesWindows(protoBinPath, protoBinSuffix, directoryFiles);
100 #elif PANDA_TARGET_UNIX
101     return EnumerateFilesUnix(protoBinPath, protoBinSuffix, directoryFiles);
102 #endif
103 }
104 
AppendProtoFiles(const std::string & filePath,const std::string & protoBinSuffix,std::vector<std::string> & protoFiles)105 bool MergeProgram::AppendProtoFiles(const std::string &filePath, const std::string &protoBinSuffix,
106                                     std::vector<std::string> &protoFiles)
107 {
108     auto inputAbs = panda::os::file::File::GetAbsolutePath(filePath);
109     if (!inputAbs) {
110         std::cerr << "Failed to open: " << filePath << std::endl;
111         return false;
112     }
113 
114     auto fPath = inputAbs.Value();
115     if (panda::os::file::File::IsRegularFile(fPath)) {
116         if (filePath.substr(filePath.find_last_of(".") + 1).compare(protoBinSuffix) == 0) {
117             protoFiles.emplace_back(fPath);
118         }
119     } else if (panda::os::file::File::IsDirectory(fPath)) {
120         std::vector<std::string> directoryFiles;
121         if (!GetProtoFiles(fPath, protoBinSuffix, directoryFiles)) {
122             return false;
123         }
124         protoFiles.insert(protoFiles.end(), directoryFiles.begin(), directoryFiles.end());
125     } else {
126         std::cerr << "The input path: " << fPath << " must be either a regular file or directory." << std::endl;
127         return false;
128     }
129 
130     return true;
131 }
132 
CollectProtoFiles(std::string & input,const std::string & protoBinSuffix,std::vector<std::string> & protoFiles)133 bool MergeProgram::CollectProtoFiles(std::string &input, const std::string &protoBinSuffix,
134                                      std::vector<std::string> &protoFiles)
135 {
136     constexpr const char DOGGY = '@';
137     std::vector<std::string> inputs;
138     bool isList = false;
139 
140     if (input[0] == DOGGY) {
141         input.erase(input.begin() + 0);
142         isList = true;
143     }
144 
145     auto inputAbs = panda::os::file::File::GetAbsolutePath(input);
146     if (!inputAbs) {
147         std::cerr << "Failed to open: " << input << std::endl;
148         return false;
149     }
150     if (isList) {
151         std::ifstream in(panda::os::file::File::GetExtendedFilePath(inputAbs.Value()));
152         std::string line;
153         constexpr const char CARRIAGE = '\r';
154         while (getline(in, line)) {
155             // erase front spaces
156             line.erase(line.begin(),
157                        std::find_if(line.begin(), line.end(), [](unsigned char ch) { return std::isspace(ch) == 0; }));
158             // erase carrige return symbol (Windows workaround)
159             line.erase(std::find_if(line.rbegin(), line.rend(), [](unsigned char ch) { return ch != CARRIAGE; }).base(),
160                        line.end());
161             if (!line.empty()) {
162                 inputs.push_back(line);
163             }
164         }
165         in.close();
166     } else {
167         inputs.push_back(inputAbs.Value());
168     }
169 
170     protoFiles.reserve(inputs.size());
171     for (auto &filePath : inputs) {
172         if (!AppendProtoFiles(filePath, protoBinSuffix, protoFiles)) {
173             return false;
174         }
175     }
176 
177     return true;
178 }
179 } // namespace panda::proto
180