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

Last change on this file since 5795 was 5786, checked in by cameron, 15 months ago

Decouple Unicode property support from re_compiler; initial support for (?-m) flag

File size: 6.7 KB
RevLine 
[3850]1/*
[5692]2 *  Copyright (c) 2014-7 International Characters.
[3850]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
[4961]7#include <cstdio>
[5025]8#include <vector>
[4730]9#include <llvm/Support/CommandLine.h>
[5161]10#include <llvm/Support/ErrorHandling.h>
11#include <llvm/Support/Signals.h>
[5267]12#include <llvm/Support/raw_ostream.h>
[4968]13#include <re/re_alt.h>
[5197]14#include <re/re_seq.h>
15#include <re/re_start.h>
16#include <re/re_end.h>
[4734]17#include <re/re_parser.h>
[5197]18#include <re/re_utility.h>
[4946]19#include <grep_engine.h>
[5476]20#include <grep_interface.h>
[4968]21#include <fstream>
22#include <string>
[5425]23#include <toolchain/toolchain.h>
[5030]24#include <re/re_toolchain.h>
[5031]25#include <pablo/pablo_toolchain.h>
[5163]26#include <boost/filesystem.hpp>
[5016]27#include <iostream> // MEEE
[5156]28#ifdef PRINT_TIMING_INFORMATION
29#include <hrtime.h>
30#include <util/papi_helper.hpp>
31#endif
[5418]32#include <sys/stat.h>
33#include <fcntl.h>
[5156]34
[5267]35using namespace llvm;
36
[4544]37static cl::list<std::string> inputFiles(cl::Positional, cl::desc("<regex> <input file ...>"), cl::OneOrMore);
38
[5554]39static cl::opt<bool> ByteMode("enable-byte-mode", cl::desc("Process regular expressions in byte mode"));
40
[5480]41static cl::opt<bool> MultiGrepKernels("enable-multigrep-kernels", cl::desc("Construct separated kernels for each regular expression"));
[5344]42static cl::opt<int> REsPerGroup("re-num", cl::desc("Number of regular expressions processed by each kernel."), cl::init(1));
[5550]43
[5786]44static re::ModeFlagSet globalFlags = re::MULTILINE_MODE_FLAG;
[4734]45
[5418]46std::vector<re::RE *> readExpressions() {
[4734]47 
[5480]48    if (grep::FileFlag != "") {
49        std::ifstream regexFile(grep::FileFlag.c_str());
[4734]50        std::string r;
51        if (regexFile.is_open()) {
52            while (std::getline(regexFile, r)) {
[5480]53                grep::RegexpVector.push_back(r);
[4734]54            }
55            regexFile.close();
56        }
57    }
58   
59    // if there are no regexes specified through -e or -f, the first positional argument
60    // must be a regex, not an input file.
61   
[5480]62    if (grep::RegexpVector.size() == 0) {
63        grep::RegexpVector.push_back(inputFiles[0]);
[5015]64        inputFiles.erase(inputFiles.begin());
[4734]65    }
[5473]66    if (grep::IgnoreCaseFlag) {
[5418]67        globalFlags |= re::CASE_INSENSITIVE_MODE_FLAG;
68    }
[4734]69
[5344]70    std::vector<re::RE *> REs;
[5480]71    for (unsigned i = 0; i < grep::RegexpVector.size(); i++) {
[5554]72        re::RE * re_ast = re::RE_Parser::parse(grep::RegexpVector[i], globalFlags, grep::RegexpSyntax, ByteMode);
[4734]73        REs.push_back(re_ast);
74    }
[5344]75
[5418]76    if (MultiGrepKernels) {
77        std::vector<re::RE *> groups;
78        auto start = REs.begin();
79        auto end = start + REsPerGroup;
80        while (end < REs.end()) {
81            groups.push_back(re::makeAlt(start, end));
82            start = end;
83            end += REsPerGroup;
84        }
85        if ((REs.end() - start) > 1) {
86            groups.push_back(re::makeAlt(start, REs.end()));
87        } else {
88            groups.push_back(*start);
89        }
90        REs.swap(groups);
91    } else if (REs.size() > 1) {
[5620]92        REs.assign({re::makeAlt(REs.begin(), REs.end())});
[5344]93    }
94
[5418]95    for (re::RE *& re_ast : REs) {
[5620]96        assert (re_ast);
[5473]97        if (grep::WordRegexpFlag) {
[5418]98            re_ast = re::makeSeq({re::makeWordBoundary(), re_ast, re::makeWordBoundary()});
99        }
[5473]100        if (grep::LineRegexpFlag) {
[5418]101            re_ast = re::makeSeq({re::makeStart(), re_ast, re::makeEnd()});
102        }
[4734]103    }
[5418]104
105    return REs;
[4734]106}
107
[4967]108
[5163]109// This is a stub, to be expanded later.
110bool excludeDirectory(boost::filesystem::path dirpath) { return dirpath.filename() == ".svn";}
111
[5480]112// Determine whether to skip a path based on -D skip or -d skip settings.
113bool skip_path(boost::filesystem::path p) {
114    using namespace boost::filesystem;
115    switch (status(p).type()) {
116        case directory_file: return grep::DirectoriesFlag == grep::Skip;
117        case block_file:
118        case character_file:
119        case fifo_file:
120        case socket_file:
121            return grep::DevicesFlag == grep::Skip;
122        default:
123            return false;
124    }
125}
126
[5163]127std::vector<std::string> getFullFileList(cl::list<std::string> & inputFiles) {
128    using namespace boost::filesystem;
[5473]129    symlink_option follow_symlink = grep::DereferenceRecursiveFlag ? symlink_option::recurse : symlink_option::none;
[5163]130    std::vector<std::string> expanded_paths;
131    boost::system::error_code errc;
[5379]132    for (const std::string & f : inputFiles) {
[5480]133        //        if (f == "-") {
134        //            continue;
135        //        }
[5163]136        path p(f);
[5480]137        if (skip_path(p)) {
138            continue;
139        }
140        if (LLVM_UNLIKELY((grep::DirectoriesFlag == grep::Recurse) && is_directory(p))) {
[5163]141            if (!excludeDirectory(p)) {
142                recursive_directory_iterator di(p, follow_symlink, errc), end;
143                if (errc) {
144                    // If we cannot enter the directory, keep it in the list of files.
[5480]145                    expanded_paths.push_back(f);
[5163]146                    continue;
147                }
148                while (di != end) {
149                    auto & e = di->path();
150                    if (is_directory(e)) {
[5379]151                        if (LLVM_UNLIKELY(excludeDirectory(e))) {
152                            di.no_push();
153                        }
154                    } else {
[5480]155                        if (!skip_path(e)) expanded_paths.push_back(e.string());
[5163]156                    }
157                    di.increment(errc);
158                    if (errc) {
[5480]159                        expanded_paths.push_back(e.string());
[5163]160                    }
161                }
162            }
[5379]163        } else {
164            expanded_paths.push_back(p.string());
[5163]165        }
166    }
167    return expanded_paths;
168}
169
[4325]170int main(int argc, char *argv[]) {
[5476]171
172    grep::InitializeCommandLineInterface(argc, argv);
[5473]173   
[5418]174    const auto REs = readExpressions();
175
[5700]176    std::vector<std::string> allFiles = getFullFileList(inputFiles);
[5693]177    if (allFiles.empty()) {
178        allFiles = { "-" };
179    }
180    else if ((allFiles.size() > 1) && !grep::NoFilenameFlag) {
[5692]181        grep::WithFilenameFlag = true;
182    }
[5379]183
[5706]184    grep::GrepEngine * grepEngine = nullptr;
[5698]185   
[5700]186    switch (grep::Mode) {
187        case grep::NormalMode:
[5703]188            grepEngine = new grep::EmitMatchesEngine(); break;
[5700]189        case grep::CountOnly:
[5703]190            grepEngine = new grep::CountOnlyEngine(); break;
[5700]191        case grep::FilesWithMatch:
192        case grep::FilesWithoutMatch:
[5704]193            grepEngine = new grep::MatchOnlyEngine(grep::Mode == grep::FilesWithoutMatch); break;
[5700]194        case grep::QuietMode:
[5704]195            grepEngine = new grep::QuietModeEngine(); break;
[5706]196        default: llvm_unreachable("Invalid grep mode!");
[5698]197    }
[5486]198               
[5698]199    grepEngine->grepCodeGen(REs);
[5377]200
[5698]201    grepEngine->initFileResult(allFiles);
[5377]202   
[5703]203    bool matchFound = grepEngine->searchAllFiles();
[5700]204   
[5698]205    delete(grepEngine);
206   
[5703]207    return matchFound ? grep::MatchFoundExitCode : grep::MatchNotFoundExitCode;
[3850]208}
Note: See TracBrowser for help on using the repository browser.