source: icGREP/icgrep-devel/icgrep/icgrep.cpp @ 5484

Last change on this file since 5484 was 5484, checked in by cameron, 22 months ago

Handle non-existent files, directories=read mode, -s

File size: 7.5 KB
Line 
1/*
2 *  Copyright (c) 2016 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 *  icgrep is a trademark of International Characters.
5 */
6
7#include <cstdio>
8#include <vector>
9#include <llvm/Support/CommandLine.h>
10#include <llvm/Support/ErrorHandling.h>
11#include <llvm/Support/Signals.h>
12#include <llvm/Support/raw_ostream.h>
13#include <re/re_alt.h>
14#include <re/re_seq.h>
15#include <re/re_start.h>
16#include <re/re_end.h>
17#include <re/re_parser.h>
18#include <re/re_utility.h>
19#include <grep_engine.h>
20#include <grep_interface.h>
21#include <fstream>
22#include <string>
23#include <toolchain/toolchain.h>
24#include <re/re_toolchain.h>
25#include <pablo/pablo_toolchain.h>
26#include <boost/filesystem.hpp>
27#include <iostream> // MEEE
28#ifdef PRINT_TIMING_INFORMATION
29#include <hrtime.h>
30#include <util/papi_helper.hpp>
31#endif
32#include <sys/stat.h>
33#include <fcntl.h>
34
35using namespace llvm;
36
37static cl::opt<bool> UTF_16("UTF-16", cl::desc("Regular expressions over the UTF-16 representation of Unicode."));
38
39static cl::list<std::string> inputFiles(cl::Positional, cl::desc("<regex> <input file ...>"), cl::OneOrMore);
40
41static cl::opt<int> Threads("t", cl::desc("Total number of threads."), cl::init(1));
42
43static cl::opt<bool> MultiGrepKernels("enable-multigrep-kernels", cl::desc("Construct separated kernels for each regular expression"));
44static cl::opt<int> REsPerGroup("re-num", cl::desc("Number of regular expressions processed by each kernel."), cl::init(1));
45static std::vector<std::string> allFiles;
46
47static re::ModeFlagSet globalFlags = 0;
48
49std::vector<re::RE *> readExpressions() {
50 
51    if (grep::FileFlag != "") {
52        std::ifstream regexFile(grep::FileFlag.c_str());
53        std::string r;
54        if (regexFile.is_open()) {
55            while (std::getline(regexFile, r)) {
56                grep::RegexpVector.push_back(r);
57            }
58            regexFile.close();
59        }
60    }
61   
62    // if there are no regexes specified through -e or -f, the first positional argument
63    // must be a regex, not an input file.
64   
65    if (grep::RegexpVector.size() == 0) {
66        grep::RegexpVector.push_back(inputFiles[0]);
67        inputFiles.erase(inputFiles.begin());
68    }
69    if (grep::IgnoreCaseFlag) {
70        globalFlags |= re::CASE_INSENSITIVE_MODE_FLAG;
71    }
72
73    std::vector<re::RE *> REs;
74    for (unsigned i = 0; i < grep::RegexpVector.size(); i++) {
75        re::RE * re_ast = re::RE_Parser::parse(grep::RegexpVector[i], globalFlags, grep::RegexpSyntax);
76        REs.push_back(re_ast);
77    }
78
79    if (MultiGrepKernels) {
80        std::vector<re::RE *> groups;
81        auto start = REs.begin();
82        auto end = start + REsPerGroup;
83        while (end < REs.end()) {
84            groups.push_back(re::makeAlt(start, end));
85            start = end;
86            end += REsPerGroup;
87        }
88        if ((REs.end() - start) > 1) {
89            groups.push_back(re::makeAlt(start, REs.end()));
90        } else {
91            groups.push_back(*start);
92        }
93        REs.swap(groups);
94    } else if (REs.size() > 1) {
95        re::RE * re_ast = re::makeAlt(REs.begin(), REs.end());
96        REs.assign({re_ast});
97    }
98
99    for (re::RE *& re_ast : REs) {
100        if (grep::WordRegexpFlag) {
101            re_ast = re::makeSeq({re::makeWordBoundary(), re_ast, re::makeWordBoundary()});
102        }
103        if (grep::LineRegexpFlag) {
104            re_ast = re::makeSeq({re::makeStart(), re_ast, re::makeEnd()});
105        }
106    }
107
108    return REs;
109}
110
111
112// This is a stub, to be expanded later.
113bool excludeDirectory(boost::filesystem::path dirpath) { return dirpath.filename() == ".svn";}
114
115// Determine whether to skip a path based on -D skip or -d skip settings.
116bool skip_path(boost::filesystem::path p) {
117    using namespace boost::filesystem;
118    switch (status(p).type()) {
119        case directory_file: return grep::DirectoriesFlag == grep::Skip;
120        case block_file:
121        case character_file:
122        case fifo_file:
123        case socket_file:
124            return grep::DevicesFlag == grep::Skip;
125        default:
126            return false;
127    }
128}
129
130std::vector<std::string> getFullFileList(cl::list<std::string> & inputFiles) {
131    using namespace boost::filesystem;
132    symlink_option follow_symlink = grep::DereferenceRecursiveFlag ? symlink_option::recurse : symlink_option::none;
133    std::vector<std::string> expanded_paths;
134    boost::system::error_code errc;
135    for (const std::string & f : inputFiles) {
136        //        if (f == "-") {
137        //            continue;
138        //        }
139        path p(f);
140        if (skip_path(p)) {
141            continue;
142        }
143        if (LLVM_UNLIKELY((grep::DirectoriesFlag == grep::Recurse) && is_directory(p))) {
144            if (!excludeDirectory(p)) {
145                recursive_directory_iterator di(p, follow_symlink, errc), end;
146                if (errc) {
147                    // If we cannot enter the directory, keep it in the list of files.
148                    expanded_paths.push_back(f);
149                    continue;
150                }
151                while (di != end) {
152                    auto & e = di->path();
153                    if (is_directory(e)) {
154                        if (LLVM_UNLIKELY(excludeDirectory(e))) {
155                            di.no_push();
156                        }
157                    } else {
158                        if (!skip_path(e)) expanded_paths.push_back(e.string());
159                    }
160                    di.increment(errc);
161                    if (errc) {
162                        expanded_paths.push_back(e.string());
163                    }
164                }
165            }
166        } else {
167            expanded_paths.push_back(p.string());
168        }
169    }
170    return expanded_paths;
171}
172
173int main(int argc, char *argv[]) {
174
175    grep::InitializeCommandLineInterface(argc, argv);
176   
177    const auto REs = readExpressions();
178
179    allFiles = getFullFileList(inputFiles);
180
181    grep::GrepEngine grepEngine;
182
183    if (allFiles.empty()) {
184
185        grepEngine.grepCodeGen(REs, grep::Mode, UTF_16, GrepSource::StdIn);
186        allFiles = { "-" };
187        grep::initFileResult(allFiles);
188        grepEngine.doGrep(STDIN_FILENO, 0);
189
190    } else {
191       
192        setNVPTXOption();
193       
194        if (codegen::NVPTX) {
195            grepEngine.grepCodeGen_nvptx(REs, grep::Mode, UTF_16);
196            for (unsigned i = 0; i != allFiles.size(); ++i) {
197                grepEngine.doGrep(allFiles[i]);
198            }
199            return 0;
200        } else {
201            grepEngine.grepCodeGen(REs, grep::Mode, UTF_16, GrepSource::File);
202        }
203
204        grep::initFileResult(allFiles);
205
206        if (Threads <= 1) {
207            for (unsigned i = 0; i != allFiles.size(); ++i) {
208                grepEngine.doGrep(allFiles[i], i);
209            }
210        } else if (Threads > 1) {
211            const unsigned numOfThreads = Threads; // <- convert the command line value into an integer to allow stack allocation
212            pthread_t threads[numOfThreads];
213
214            for(unsigned long i = 0; i < numOfThreads; ++i){
215                const int rc = pthread_create(&threads[i], nullptr, grep::DoGrepThreadFunction, (void *)&grepEngine);
216                if (rc) {
217                    llvm::report_fatal_error("Failed to create thread: code " + std::to_string(rc));
218                }
219            }
220            for(unsigned i = 0; i < numOfThreads; ++i) {
221                void * status = nullptr;
222                const int rc = pthread_join(threads[i], &status);
223                if (rc) {
224                    llvm::report_fatal_error("Failed to join thread: code " + std::to_string(rc));
225                }
226            }
227        }
228
229    }
230   
231    grep::PrintResults();
232   
233    return 0;
234}
Note: See TracBrowser for help on using the repository browser.