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

Last change on this file since 5938 was 5938, checked in by cameron, 12 months ago

Parser reorganization step; initial check-in for FileGLOB parser

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