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

Last change on this file since 5516 was 5486, checked in by nmedfort, 23 months ago

Initial attempt to improve debugging capabilities with compilation stack traces on error.

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        if (codegen::NVPTX) {
193            grepEngine.grepCodeGen_nvptx(REs, grep::Mode, UTF_16);
194            for (unsigned i = 0; i != allFiles.size(); ++i) {
195                grepEngine.doGrep(allFiles[i]);
196            }
197            return 0;
198        } else {
199            grepEngine.grepCodeGen(REs, grep::Mode, UTF_16, GrepSource::File);
200        }
201
202        grep::initFileResult(allFiles);
203
204        if (Threads <= 1) {
205            for (unsigned i = 0; i != allFiles.size(); ++i) {
206                grepEngine.doGrep(allFiles[i], i);
207            }
208        } else if (Threads > 1) {
209            const unsigned numOfThreads = Threads; // <- convert the command line value into an integer to allow stack allocation
210            pthread_t threads[numOfThreads];
211
212            for(unsigned long i = 0; i < numOfThreads; ++i){
213                const int rc = pthread_create(&threads[i], nullptr, grep::DoGrepThreadFunction, (void *)&grepEngine);
214                if (rc) {
215                    llvm::report_fatal_error("Failed to create thread: code " + std::to_string(rc));
216                }
217            }
218            for(unsigned i = 0; i < numOfThreads; ++i) {
219                void * status = nullptr;
220                const int rc = pthread_join(threads[i], &status);
221                if (rc) {
222                    llvm::report_fatal_error("Failed to join thread: code " + std::to_string(rc));
223                }
224            }
225        }
226
227    }
228   
229    grep::PrintResults();
230   
231    return 0;
232}
Note: See TracBrowser for help on using the repository browser.