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

Last change on this file since 5895 was 5894, checked in by cameron, 17 months ago

Line break controls for Unicode/LF/Null - initial check in

File size: 7.0 KB
Line 
1/*
2 *  Copyright (c) 2014-8 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/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::list<std::string> inputFiles(cl::Positional, cl::desc("<regex> <input file ...>"), cl::OneOrMore);
38
39static cl::opt<bool> UnixBreaks("Unix-line-breaks", cl::desc("Enable Unix line breaks"));
40static cl::opt<bool> ByteMode("enable-byte-mode", cl::desc("Process regular expressions in byte mode"));
41
42static cl::opt<bool> MultiGrepKernels("enable-multigrep-kernels", cl::desc("Construct separated kernels for each regular expression"));
43static cl::opt<int> REsPerGroup("re-num", cl::desc("Number of regular expressions processed by each kernel."), cl::init(1));
44
45static re::ModeFlagSet globalFlags = re::MULTILINE_MODE_FLAG;
46
47std::vector<re::RE *> readExpressions() {
48 
49    if (grep::FileFlag != "") {
50        std::ifstream regexFile(grep::FileFlag.c_str());
51        std::string r;
52        if (regexFile.is_open()) {
53            while (std::getline(regexFile, r)) {
54                grep::RegexpVector.push_back(r);
55            }
56            regexFile.close();
57        }
58    }
59   
60    // if there are no regexes specified through -e or -f, the first positional argument
61    // must be a regex, not an input file.
62   
63    if (grep::RegexpVector.size() == 0) {
64        grep::RegexpVector.push_back(inputFiles[0]);
65        inputFiles.erase(inputFiles.begin());
66    }
67    if (grep::IgnoreCaseFlag) {
68        globalFlags |= re::CASE_INSENSITIVE_MODE_FLAG;
69    }
70
71    std::vector<re::RE *> REs;
72    for (unsigned i = 0; i < grep::RegexpVector.size(); i++) {
73        re::RE * re_ast = re::RE_Parser::parse(grep::RegexpVector[i], globalFlags, grep::RegexpSyntax, ByteMode);
74        REs.push_back(re_ast);
75    }
76
77    if (MultiGrepKernels) {
78        std::vector<re::RE *> groups;
79        auto start = REs.begin();
80        auto end = start + REsPerGroup;
81        while (end < REs.end()) {
82            groups.push_back(re::makeAlt(start, end));
83            start = end;
84            end += REsPerGroup;
85        }
86        if ((REs.end() - start) > 1) {
87            groups.push_back(re::makeAlt(start, REs.end()));
88        } else {
89            groups.push_back(*start);
90        }
91        REs.swap(groups);
92    } else if (REs.size() > 1) {
93        REs.assign({re::makeAlt(REs.begin(), REs.end())});
94    }
95
96    for (re::RE *& re_ast : REs) {
97        assert (re_ast);
98        if (grep::WordRegexpFlag) {
99            re_ast = re::makeSeq({re::makeWordBoundary(), re_ast, re::makeWordBoundary()});
100        }
101        if (grep::LineRegexpFlag) {
102            re_ast = re::makeSeq({re::makeStart(), re_ast, re::makeEnd()});
103        }
104    }
105
106    return REs;
107}
108
109
110// This is a stub, to be expanded later.
111bool excludeDirectory(boost::filesystem::path dirpath) { return dirpath.filename() == ".svn";}
112
113// Determine whether to skip a path based on -D skip or -d skip settings.
114bool skip_path(boost::filesystem::path p) {
115    using namespace boost::filesystem;
116    switch (status(p).type()) {
117        case directory_file: return grep::DirectoriesFlag == grep::Skip;
118        case block_file:
119        case character_file:
120        case fifo_file:
121        case socket_file:
122            return grep::DevicesFlag == grep::Skip;
123        default:
124            return false;
125    }
126}
127
128std::vector<std::string> getFullFileList(cl::list<std::string> & inputFiles) {
129    using namespace boost::filesystem;
130    symlink_option follow_symlink = grep::DereferenceRecursiveFlag ? symlink_option::recurse : symlink_option::none;
131    std::vector<std::string> expanded_paths;
132    boost::system::error_code errc;
133    for (const std::string & f : inputFiles) {
134        //        if (f == "-") {
135        //            continue;
136        //        }
137        path p(f);
138        if (skip_path(p)) {
139            continue;
140        }
141        if (LLVM_UNLIKELY((grep::DirectoriesFlag == grep::Recurse) && is_directory(p))) {
142            if (!excludeDirectory(p)) {
143                recursive_directory_iterator di(p, follow_symlink, errc), end;
144                if (errc) {
145                    // If we cannot enter the directory, keep it in the list of files.
146                    expanded_paths.push_back(f);
147                    continue;
148                }
149                while (di != end) {
150                    auto & e = di->path();
151                    if (is_directory(e)) {
152                        if (LLVM_UNLIKELY(excludeDirectory(e))) {
153                            di.no_push();
154                        }
155                    } else {
156                        if (!skip_path(e)) expanded_paths.push_back(e.string());
157                    }
158                    di.increment(errc);
159                    if (errc) {
160                        expanded_paths.push_back(e.string());
161                    }
162                }
163            }
164        } else {
165            expanded_paths.push_back(p.string());
166        }
167    }
168    return expanded_paths;
169}
170
171int main(int argc, char *argv[]) {
172
173    grep::InitializeCommandLineInterface(argc, argv);
174   
175    const auto REs = readExpressions();
176
177    std::vector<std::string> allFiles = getFullFileList(inputFiles);
178    if (allFiles.empty()) {
179        allFiles = { "-" };
180    }
181    else if ((allFiles.size() > 1) && !grep::NoFilenameFlag) {
182        grep::WithFilenameFlag = true;
183    }
184
185    grep::GrepEngine * grepEngine = nullptr;
186   
187    switch (grep::Mode) {
188        case grep::NormalMode:
189            grepEngine = new grep::EmitMatchesEngine(); break;
190        case grep::CountOnly:
191            grepEngine = new grep::CountOnlyEngine(); break;
192        case grep::FilesWithMatch:
193        case grep::FilesWithoutMatch:
194            grepEngine = new grep::MatchOnlyEngine(grep::Mode == grep::FilesWithoutMatch); break;
195        case grep::QuietMode:
196            grepEngine = new grep::QuietModeEngine(); break;
197        default: llvm_unreachable("Invalid grep mode!");
198    }
199               
200    if (UnixBreaks) {
201        grepEngine->setRecordBreak(grep::GrepRecordBreakKind::LF);
202    } else if (grep::NullDataFlag) {
203        grepEngine->setRecordBreak(grep::GrepRecordBreakKind::Null);
204    }
205   
206    grepEngine->grepCodeGen(REs);
207
208    grepEngine->initFileResult(allFiles);
209   
210    bool matchFound = grepEngine->searchAllFiles();
211   
212    delete(grepEngine);
213   
214    return matchFound ? grep::MatchFoundExitCode : grep::MatchNotFoundExitCode;
215}
Note: See TracBrowser for help on using the repository browser.