• 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 {
GetProtoFiles(const std::string & protoBinPath,const std::string & protoBinSuffix,std::vector<std::string> & directoryFiles)32 bool MergeProgram::GetProtoFiles(const std::string &protoBinPath, const std::string &protoBinSuffix,
33                                  std::vector<std::string> &directoryFiles)
34 {
35 #if PANDA_TARGET_WINDOWS
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 #elif PANDA_TARGET_UNIX
61     DIR *protoBin = opendir(protoBinPath.c_str());
62     if (protoBin == nullptr) {
63         return false;
64     }
65     dirent *dir = nullptr;
66     std::string pathPrefix = protoBinPath + "/";
67     while ((dir = readdir(protoBin)) != nullptr) {
68         if((!strncmp(dir->d_name, ".", 1)) || (!strncmp(dir->d_name, "..", 2))) {
69             continue;
70         }
71         if (dir->d_type == DT_DIR) {
72             std::string subDirName = pathPrefix + dir->d_name;
73             if (!GetProtoFiles(subDirName, protoBinSuffix, directoryFiles)) {
74                 closedir(protoBin);
75                 return false;
76             }
77         } else {
78             std::string fileName = pathPrefix + dir->d_name;
79             if (fileName.substr(fileName.find_last_of(".") + 1).compare(protoBinSuffix) == 0) {
80                 directoryFiles.emplace_back(fileName);
81             }
82         }
83     }
84     closedir(protoBin);
85 #endif
86     return true;
87 }
88 
AppendProtoFiles(const std::string & filePath,const std::string & protoBinSuffix,std::vector<std::string> & protoFiles)89 bool MergeProgram::AppendProtoFiles(const std::string &filePath, const std::string &protoBinSuffix,
90                                     std::vector<std::string> &protoFiles)
91 {
92     auto inputAbs = panda::os::file::File::GetAbsolutePath(filePath);
93     if (!inputAbs) {
94         std::cerr << "Failed to open: " << filePath << std::endl;
95         return false;
96     }
97 
98     auto fPath = inputAbs.Value();
99     if (panda::os::file::File::IsRegularFile(fPath)) {
100         if (filePath.substr(filePath.find_last_of(".") + 1).compare(protoBinSuffix) == 0) {
101             protoFiles.emplace_back(fPath);
102         }
103     } else if (panda::os::file::File::IsDirectory(fPath)) {
104         std::vector<std::string> directoryFiles;
105         if (!GetProtoFiles(fPath, protoBinSuffix, directoryFiles)) {
106             return false;
107         }
108         protoFiles.insert(protoFiles.end(), directoryFiles.begin(), directoryFiles.end());
109     } else {
110         std::cerr << "The input path: " << fPath << " must be either a regular file or directory." << std::endl;
111         return false;
112     }
113 
114     return true;
115 }
116 
CollectProtoFiles(std::string & input,const std::string & protoBinSuffix,std::vector<std::string> & protoFiles)117 bool MergeProgram::CollectProtoFiles(std::string &input, const std::string &protoBinSuffix,
118                                      std::vector<std::string> &protoFiles)
119 {
120     constexpr const char DOGGY = '@';
121     std::vector<std::string> inputs;
122     bool isList = false;
123 
124     if (input[0] == DOGGY) {
125         input.erase(input.begin() + 0);
126         isList = true;
127     }
128 
129     auto inputAbs = panda::os::file::File::GetAbsolutePath(input);
130     if (!inputAbs) {
131         std::cerr << "Failed to open: " << input << std::endl;
132         return false;
133     }
134     if (isList) {
135         std::ifstream in(panda::os::file::File::GetExtendedFilePath(inputAbs.Value()));
136         std::string line;
137         constexpr const char CARRIAGE = '\r';
138         while (getline(in, line)) {
139             // erase front spaces
140             line.erase(line.begin(),
141                        std::find_if(line.begin(), line.end(), [](unsigned char ch) { return std::isspace(ch) == 0; }));
142             // erase carrige return symbol (Windows workaround)
143             line.erase(std::find_if(line.rbegin(), line.rend(), [](unsigned char ch) { return ch != CARRIAGE; }).base(),
144                        line.end());
145             if (!line.empty()) {
146                 inputs.push_back(line);
147             }
148         }
149         in.close();
150     } else {
151         inputs.push_back(inputAbs.Value());
152     }
153 
154     protoFiles.reserve(inputs.size());
155     for (auto &filePath : inputs) {
156         if (!AppendProtoFiles(filePath, protoBinSuffix, protoFiles)) {
157             return false;
158         }
159     }
160 
161     return true;
162 }
163 } // namespace panda::proto
164