forked from boostorg/regex
Rewritten grep example program.
"touched" some of the sources to force regression tests to rebuild. Split test code up some more to help msvc-stlport. [SVN r26705]
This commit is contained in:
@ -53,13 +53,10 @@
|
||||
<P>Directory: <A href="../test/captures">libs/test/captures</A>.</P>
|
||||
<P>Files: <A href="../test/captures/captures_test.cpp">captures_test.cpp</A>.</P>
|
||||
<H3>Example programs</H3>
|
||||
<H4>jgrep.exe</H4>
|
||||
<P>A simple grep implementation, run with no command line options to find out its
|
||||
usage. Look at <A href="../src/fileiter.cpp">fileiter.cpp</A>/fileiter.hpp and
|
||||
the mapfile class to see an example of a "smart" bidirectional iterator that
|
||||
can be used with boost.regex or any other STL algorithm.</P>
|
||||
<P>Files: <A href="../example/jgrep/jgrep.cpp">jgrep.cpp</A>, <A href="../example/jgrep/main.cpp">
|
||||
main.cpp</A>.</P>
|
||||
<H4>grep</H4>
|
||||
<P>A simple grep implementation, run with the -h command line option to find out
|
||||
its usage.</P>
|
||||
<P>Files: <A href="../example/grep/grep.cpp">grep.cpp</A></P>
|
||||
<H4>timer.exe</H4>
|
||||
<P>A simple interactive expression matching application, the results of all
|
||||
matches are timed, allowing the programmer to optimize their regular
|
||||
|
@ -53,13 +53,10 @@
|
||||
<P>Directory: <A href="../test/captures">libs/test/captures</A>.</P>
|
||||
<P>Files: <A href="../test/captures/captures_test.cpp">captures_test.cpp</A>.</P>
|
||||
<H3>Example programs</H3>
|
||||
<H4>jgrep.exe</H4>
|
||||
<P>A simple grep implementation, run with no command line options to find out its
|
||||
usage. Look at <A href="../src/fileiter.cpp">fileiter.cpp</A>/fileiter.hpp and
|
||||
the mapfile class to see an example of a "smart" bidirectional iterator that
|
||||
can be used with boost.regex or any other STL algorithm.</P>
|
||||
<P>Files: <A href="../example/jgrep/jgrep.cpp">jgrep.cpp</A>, <A href="../example/jgrep/main.cpp">
|
||||
main.cpp</A>.</P>
|
||||
<H4>grep</H4>
|
||||
<P>A simple grep implementation, run with the -h command line option to find out
|
||||
its usage.</P>
|
||||
<P>Files: <A href="../example/grep/grep.cpp">grep.cpp</A></P>
|
||||
<H4>timer.exe</H4>
|
||||
<P>A simple interactive expression matching application, the results of all
|
||||
matches are timed, allowing the programmer to optimize their regular
|
||||
|
@ -63,7 +63,7 @@ rule regex-test-run ( sources + : input * )
|
||||
test-suite regex-examples :
|
||||
|
||||
[ regex-test-run timer/regex_timer.cpp <template>../build/msvc-stlport-tricky : $(BOOST_ROOT)/libs/regex/example/timer/input_script.txt ]
|
||||
[ regex-test-run jgrep/jgrep.cpp jgrep/main.cpp : -n boost/ $(BOOST_ROOT)/boost/regex.hpp ]
|
||||
[ regex-test-run grep/grep.cpp <lib>../../program_options/build/boost_program_options : -n -b $(BOOST_ROOT)/boost/regex.hpp $(BOOST_ROOT)/boost/type_traits.hpp ]
|
||||
[ regex-test-run snippets/credit_card_example.cpp ]
|
||||
[ regex-test-run snippets/mfc_example.cpp ]
|
||||
[ regex-test-run snippets/icu_example.cpp ]
|
||||
|
@ -24,7 +24,7 @@ rule regex-test-run ( sources + : input * )
|
||||
test-suite regex-examples :
|
||||
|
||||
[ regex-test-run timer/regex_timer.cpp : $(BOOST_ROOT)/libs/regex/example/timer/input_script.txt ]
|
||||
[ regex-test-run jgrep/jgrep.cpp jgrep/main.cpp : -n boost/ $(BOOST_ROOT)/boost/regex.hpp ]
|
||||
[ regex-test-run grep/grep.cpp ../../program_options/build//program_options : -n -b $(BOOST_ROOT)/boost/regex.hpp $(BOOST_ROOT)/boost/type_traits.hpp ]
|
||||
[ regex-test-run snippets/credit_card_example.cpp ]
|
||||
[ regex-test-run snippets/mfc_example.cpp ]
|
||||
[ regex-test-run snippets/icu_example.cpp ]
|
||||
|
212
example/grep/grep.cpp
Normal file
212
example/grep/grep.cpp
Normal file
@ -0,0 +1,212 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2004
|
||||
* Dr John Maddock
|
||||
*
|
||||
* Use, modification and distribution are subject to the
|
||||
* Boost Software License, Version 1.0. (See accompanying file
|
||||
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
namespace po = boost::program_options;
|
||||
|
||||
int after_context;
|
||||
int before_context;
|
||||
bool print_byte_offset;
|
||||
bool count_only;
|
||||
std::string pattern;
|
||||
bool print_non_matching_files;
|
||||
bool files_only;
|
||||
bool print_line_numbers;
|
||||
|
||||
boost::regex_constants::syntax_option_type flags = boost::regex_constants::basic;
|
||||
boost::regex re;
|
||||
boost::smatch what;
|
||||
std::string current_file;
|
||||
int file_count;
|
||||
|
||||
void process_stream(std::istream& is)
|
||||
{
|
||||
std::string line;
|
||||
int match_found = 0;
|
||||
int linenum = 1;
|
||||
while(std::getline(is, line))
|
||||
{
|
||||
bool result = boost::regex_search(line, what, re);
|
||||
if(result)
|
||||
{
|
||||
if(print_non_matching_files)
|
||||
return;
|
||||
if(files_only)
|
||||
{
|
||||
std::cout << current_file << std::endl;
|
||||
return;
|
||||
}
|
||||
if(!match_found && !count_only && (file_count > 1))
|
||||
{
|
||||
std::cout << current_file << ":\n";
|
||||
}
|
||||
++match_found;
|
||||
if(!count_only)
|
||||
{
|
||||
if(print_line_numbers)
|
||||
{
|
||||
std::cout << linenum << ":";
|
||||
}
|
||||
if(print_byte_offset)
|
||||
{
|
||||
std::cout << what.position() << ":";
|
||||
}
|
||||
std::cout << what[0] << std::endl;
|
||||
}
|
||||
}
|
||||
++linenum;
|
||||
}
|
||||
if(count_only && match_found)
|
||||
{
|
||||
std::cout << match_found << " matches found in file " << current_file << std::endl;
|
||||
}
|
||||
else if(print_non_matching_files && !match_found)
|
||||
{
|
||||
std::cout << current_file << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void process_file(const std::string& name)
|
||||
{
|
||||
current_file = name;
|
||||
std::ifstream is(name.c_str());
|
||||
if(is.bad())
|
||||
{
|
||||
std::cerr << "Unable to open file " << name << std::endl;
|
||||
}
|
||||
process_stream(is);
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
try{
|
||||
po::options_description opts("Options");
|
||||
opts.add_options()
|
||||
("help,h", "produce help message")
|
||||
//("after-context,A", po::value<int>(&after_context)->default_value(0), "Print arg lines of trailing context after matching lines. Places a line containing -- between contiguous groups of matches.")
|
||||
//("before-context,B", po::value<int>(&before_context)->default_value(0), "Print arg lines of leading context before matching lines. Places a line containing -- between contiguous groups of matches.")
|
||||
//("context,C", po::value<int>(), "Print arg lines of output context. Places a line containing -- between contiguous groups of matches.")
|
||||
("byte-offset,b", "Print the byte offset within the input file before each line of output.")
|
||||
("count,c", "Suppress normal output; instead print a count of matching lines for each input file. With the -v, --invert-match option (see below), count non-matching lines.")
|
||||
("extended-regexp,E", "Interpret PATTERN as an POSIX-extended regular expression.")
|
||||
("perl-regexp,P", "Interpret PATTERN as a Perl regular expression.")
|
||||
//("regexp,e", po::value<std::string>(&pattern), "Use PATTERN as the pattern; useful to protect patterns beginning with -.")
|
||||
("basic-regexp,G", "Interpret arg as a POSIX-basic regular expression (see below). This is the default.")
|
||||
("ignore-case,i", "Ignore case distinctions in both the PATTERN and the input files.")
|
||||
("files-without-match,L", "Suppress normal output; instead print the name of each input file from which no output would normally have been printed. The scanning will stop on the first match.")
|
||||
("files-with-matches,l", "Suppress normal output; instead print the name of each input file from which output would normally have been printed. The scanning will stop on the first match.")
|
||||
("line-number,n", "Prefix each line of output with the line number within its input file.")
|
||||
;
|
||||
// Hidden options, will be allowed both on command line and
|
||||
// in config file, but will not be shown to the user.
|
||||
po::options_description hidden("Hidden options");
|
||||
hidden.add_options()
|
||||
("input-file", po::value< std::vector<std::string> >(), "input file")
|
||||
("input-pattern", po::value< std::string >(), "input file")
|
||||
;
|
||||
|
||||
po::options_description cmdline_options;
|
||||
cmdline_options.add(opts).add(hidden);
|
||||
|
||||
po::positional_options_description p;
|
||||
p.add("input-pattern", 1);
|
||||
p.add("input-file", -1);
|
||||
|
||||
po::variables_map vm;
|
||||
store(po::command_line_parser(argc, argv).options(cmdline_options)/*.options(hidden)*/.positional(p).run(), vm);
|
||||
notify(vm);
|
||||
|
||||
if (vm.count("help"))
|
||||
{
|
||||
std::cout << opts << "\n";
|
||||
return 0;
|
||||
}
|
||||
if (vm.count("context"))
|
||||
{
|
||||
after_context = vm["context"].as< int >();
|
||||
before_context = after_context;
|
||||
}
|
||||
if(vm.count("extended-regexp"))
|
||||
{
|
||||
flags = boost::regex_constants::extended;
|
||||
}
|
||||
if(vm.count("basic-regexp"))
|
||||
{
|
||||
flags = boost::regex_constants::basic;
|
||||
}
|
||||
if(vm.count("perl-regexp"))
|
||||
{
|
||||
flags = boost::regex_constants::perl;
|
||||
}
|
||||
if(vm.count("ignore-case"))
|
||||
{
|
||||
flags |= boost::regex_constants::icase;
|
||||
}
|
||||
if(vm.count("byte-offset"))
|
||||
{
|
||||
print_byte_offset = true;
|
||||
}
|
||||
if(vm.count("count"))
|
||||
{
|
||||
count_only = true;
|
||||
}
|
||||
if(vm.count("files-without-match"))
|
||||
{
|
||||
print_non_matching_files = true;
|
||||
}
|
||||
if(vm.count("files-with-matches"))
|
||||
{
|
||||
files_only = true;
|
||||
}
|
||||
if(vm.count("line-number"))
|
||||
{
|
||||
print_line_numbers = true;
|
||||
}
|
||||
if(vm.count("input-pattern"))
|
||||
{
|
||||
pattern = vm["input-pattern"].as< std::string >();
|
||||
re.assign(pattern, flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "No pattern specified" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
if (vm.count("input-file"))
|
||||
{
|
||||
const std::vector<std::string>& files = vm["input-file"].as< std::vector<std::string> >();
|
||||
file_count = files.size();
|
||||
for(std::vector<std::string>::const_iterator i = files.begin(); i != files.end(); ++i)
|
||||
{
|
||||
process_file(*i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// no input files, scan stdin instead:
|
||||
process_stream(std::cin);
|
||||
}
|
||||
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,51 +0,0 @@
|
||||
|
||||
# very basic makefile for jgrep.exe
|
||||
#
|
||||
# Borland C++ tools
|
||||
#
|
||||
# BCROOT defines the root directory of your bc builder install
|
||||
#
|
||||
!ifndef BCROOT
|
||||
BCROOT=$(MAKEDIR)\..
|
||||
!endif
|
||||
|
||||
BCC32 = $(BCROOT)\bin\Bcc32.exe
|
||||
LIBPATH=..\..\build\bcb5
|
||||
|
||||
IDE_LinkFLAGS32 = -L$(BCROOT)\LIB
|
||||
LINKOPTS= -ap -Tpe -x
|
||||
COMPOPTS= -O2 -tWM- -Vx -Ve -DSTRICT; -I$(BCROOT)\include;../../../../; -D_NO_VCL
|
||||
|
||||
|
||||
|
||||
jgrep.exe : jgrep.obj main.obj
|
||||
$(BCC32) $(COMPOPTS) -e$@ -L$(LIBPATH) main.obj jgrep.obj
|
||||
|
||||
jgrep.obj : jgrep.cpp
|
||||
$(BCC32) -c @&&|
|
||||
$(COMPOPTS) -o$@ jgrep.cpp
|
||||
|
|
||||
|
||||
main.obj : main.cpp
|
||||
$(BCC32) -c @&&|
|
||||
$(COMPOPTS) -o$@ main.cpp
|
||||
|
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,51 +0,0 @@
|
||||
|
||||
# very basic makefile for jgrep.exe
|
||||
#
|
||||
# Borland C++ tools
|
||||
#
|
||||
# BCROOT defines the root directory of your bc builder install
|
||||
#
|
||||
!ifndef BCROOT
|
||||
BCROOT=$(MAKEDIR)\..
|
||||
!endif
|
||||
|
||||
BCC32 = $(BCROOT)\bin\Bcc32.exe
|
||||
LIBPATH="..\..\build\bcb4"
|
||||
|
||||
IDE_LinkFLAGS32 = -L$(BCROOT)\LIB
|
||||
LINKOPTS= -ap -Tpe -x
|
||||
COMPOPTS= -O2 -tWM- -Vx -Ve -DSTRICT; -I$(BCROOT)\include;../../../../; -D_NO_VCL
|
||||
|
||||
|
||||
|
||||
jgrep.exe : jgrep.obj main.obj
|
||||
$(BCC32) @&&|
|
||||
$(COMPOPTS) -e$@ -L$(LIBPATH) main.obj jgrep.obj
|
||||
|
|
||||
|
||||
jgrep.obj : jgrep.cpp
|
||||
$(BCC32) -c @&&|
|
||||
$(COMPOPTS) -o$@ jgrep.cpp
|
||||
|
|
||||
|
||||
main.obj : main.cpp
|
||||
$(BCC32) -c @&&|
|
||||
$(COMPOPTS) -o$@ main.cpp
|
||||
|
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,50 +0,0 @@
|
||||
|
||||
# very basic makefile for jgrep.exe
|
||||
#
|
||||
# Borland C++ tools
|
||||
#
|
||||
# BCROOT defines the root directory of your bc builder install
|
||||
#
|
||||
!ifndef BCROOT
|
||||
BCROOT=$(MAKEDIR)\..
|
||||
!endif
|
||||
|
||||
BCC32 = $(BCROOT)\bin\Bcc32.exe
|
||||
LIBPATH=../../build/bcb5
|
||||
|
||||
IDE_LinkFLAGS32 = -L$(BCROOT)\LIB
|
||||
LINKOPTS= -ap -Tpe -x
|
||||
COMPOPTS= -O2 -tWM- -Vx -Ve -DSTRICT; -I$(BCROOT)\include;../../../../; -D_NO_VCL
|
||||
|
||||
|
||||
|
||||
jgrep.exe : jgrep.obj main.obj
|
||||
$(BCC32) $(COMPOPTS) -e$@ -L..\..\build\bcb5 main.obj jgrep.obj
|
||||
|
||||
jgrep.obj : jgrep.cpp
|
||||
$(BCC32) -c @&&|
|
||||
$(COMPOPTS) -o$@ jgrep.cpp
|
||||
|
|
||||
|
||||
main.obj : main.cpp
|
||||
$(BCC32) -c @&&|
|
||||
$(COMPOPTS) -o$@ main.cpp
|
||||
|
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,32 +0,0 @@
|
||||
|
||||
# very basic makefile for jgrep
|
||||
#
|
||||
# GNU compiler g++
|
||||
#
|
||||
CXX= $(INCLUDES) -O2 -I../../../../ -I./ $(CXXFLAGS) $(LDFLAGS)
|
||||
|
||||
jgrep : jgrep.cpp main.cpp
|
||||
g++ -ojgrep $(CXX) jgrep.cpp main.cpp -L../../build/gcc -lboost_regex $(LIBS)
|
||||
|
||||
debug : jgrep.cpp main.cpp
|
||||
g++ -ojgrep -I../../../../ -I./ -g jgrep.cpp main.cpp -L../../build/gcc -lboost_regex_debug $(LIBS)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,148 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 1998-2002
|
||||
* Dr John Maddock
|
||||
*
|
||||
* Use, modification and distribution are subject to the
|
||||
* Boost Software License, Version 1.0. (See accompanying file
|
||||
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* FILE jgrep.cpp
|
||||
* VERSION see <boost/version.hpp>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <algorithm>
|
||||
#include <boost/regex.hpp>
|
||||
#ifdef JM_OLD_IOSTREAM
|
||||
#include <iostream.h>
|
||||
#else
|
||||
#include <iostream>
|
||||
using std::cout;
|
||||
using std::cin;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
#endif
|
||||
#ifdef __BORLANDC__
|
||||
# pragma hrdstop
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_REGEX_V3
|
||||
#include <boost/regex/v3/fileiter.hpp>
|
||||
#else
|
||||
#include <boost/regex/v4/fileiter.hpp>
|
||||
#endif
|
||||
|
||||
#include "jgrep.h"
|
||||
#ifndef BOOST_REGEX_NO_FILEITER
|
||||
|
||||
//
|
||||
// class ogrep_predicate
|
||||
// outputs the results of regex_grep to screen:
|
||||
template <class iterator, class Allocator >
|
||||
class ogrep_predicate
|
||||
{
|
||||
unsigned int& lines;
|
||||
const char* filename;
|
||||
unsigned int last_line;
|
||||
iterator end_of_storage, last_line_start;
|
||||
public:
|
||||
ogrep_predicate(unsigned int& i, const char* p, iterator start, iterator end) : lines(i), filename(p), last_line(-1), end_of_storage(end), last_line_start(start) {}
|
||||
ogrep_predicate(const ogrep_predicate& o) : lines(o.lines), filename(o.filename), last_line(o.last_line), end_of_storage(o.end_of_storage), last_line_start(o.last_line_start) {}
|
||||
bool operator () (const boost::match_results<iterator, Allocator>& i);
|
||||
private:
|
||||
void operator=(const ogrep_predicate&);
|
||||
};
|
||||
|
||||
// ideally we'd ignor the allocator type and use a template member function
|
||||
// to deel with the allocator type passed to regex_grep, unfortunately most
|
||||
// compilers don't support this feature yet, so we'll have to be sure that
|
||||
// the allocator passed to instances of this class match that used in our
|
||||
// regular expression classes.
|
||||
|
||||
template <class iterator, class Allocator>
|
||||
bool ogrep_predicate<iterator, Allocator>::operator()(const boost::match_results<iterator, Allocator>& i)
|
||||
{
|
||||
// if we haven't printed the filename yet, then do it now:
|
||||
if(last_line == (unsigned int)-1)
|
||||
{
|
||||
cout << "File " << filename << ":" << endl;
|
||||
last_line = 0;
|
||||
}
|
||||
// calculate which line we are on, by adding the number of newlines
|
||||
// we've skipped in the last search:
|
||||
unsigned int current_line = last_line + std::count(last_line_start, end_of_storage, '\n');
|
||||
// if we haven't already printed this line out, then do it now:
|
||||
if(last_line != current_line)
|
||||
{
|
||||
++lines;
|
||||
last_line = current_line;
|
||||
if(count_only == 0)
|
||||
{
|
||||
if(show_lines)
|
||||
cout << current_line << "\t";
|
||||
const char* nls = "\n";
|
||||
iterator ptr = std::find_end(last_line_start, i[0].first, nls, nls+1);
|
||||
++ptr;
|
||||
iterator ptr2 = ptr;
|
||||
while((ptr2 != end_of_storage) && (*ptr2 != '\n'))++ptr2;
|
||||
while(ptr != ptr2)
|
||||
{
|
||||
cout.put(*ptr);
|
||||
++ptr;
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
}
|
||||
// set the last line seen to the start of the current match:
|
||||
last_line_start = i[0].first;
|
||||
return true;
|
||||
}
|
||||
|
||||
using namespace boost;
|
||||
|
||||
void process_grep(const char* file)
|
||||
{
|
||||
try{
|
||||
mapfile f(file);
|
||||
unsigned int count = 0;
|
||||
ogrep_predicate<mapfile::iterator, boost::match_results<mapfile::iterator>::allocator_type> oi(count, file, f.begin(), f.end());
|
||||
if(files_only)
|
||||
{
|
||||
bool ok;
|
||||
boost::match_results<mapfile::iterator> m;
|
||||
ok = regex_search(f.begin(), f.end(), m, e, match_not_dot_newline | match_not_dot_null);
|
||||
if(ok)
|
||||
cout << "File " << file << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
regex_grep(oi, f.begin(), f.end(), e, match_not_dot_newline | match_not_dot_null);
|
||||
if(count)
|
||||
{
|
||||
if(verbose || count_only)
|
||||
{
|
||||
cout << count << " lines match" << endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if(verbose)
|
||||
{
|
||||
cout << "File " << file << "(" << f.size() << "bytes):" << endl << "0 lines match" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
std::cerr << std::endl << e.what() << std::endl;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 1998-2000
|
||||
* Dr John Maddock
|
||||
*
|
||||
* Use, modification and distribution are subject to the
|
||||
* Boost Software License, Version 1.0. (See accompanying file
|
||||
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* FILE jgrep.h
|
||||
* VERSION see <boost/version.hpp>
|
||||
*/
|
||||
|
||||
#ifndef _JGREP_H
|
||||
#define _JGREP_H
|
||||
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
typedef boost::basic_regex<char> re_type;
|
||||
extern re_type e;
|
||||
|
||||
// flags for output:
|
||||
|
||||
extern bool use_case;
|
||||
extern bool show_lines;
|
||||
extern bool count_only;
|
||||
extern bool files_only;
|
||||
extern bool recurse;
|
||||
extern bool regularexs;
|
||||
extern bool words_only;
|
||||
extern bool verbose;
|
||||
|
||||
void process_grep(const char* file);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
@ -1,289 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 1998-2002
|
||||
* Dr John Maddock
|
||||
*
|
||||
* Use, modification and distribution are subject to the
|
||||
* Boost Software License, Version 1.0. (See accompanying file
|
||||
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* FILE main.cpp
|
||||
* VERSION see <boost/version.hpp>
|
||||
*/
|
||||
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/regex/v4/fileiter.hpp>
|
||||
#include "jgrep.h"
|
||||
#ifndef BOOST_REGEX_NO_FILEITER
|
||||
|
||||
#ifdef BOOST_NO_STDC_NAMESPACE
|
||||
namespace std{
|
||||
using ::strcpy;
|
||||
using ::strcat;
|
||||
using ::sprintf;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
re_type e;
|
||||
//rei_type ei(a);
|
||||
|
||||
// flags for output:
|
||||
|
||||
bool use_case = true;
|
||||
bool show_lines = false;
|
||||
bool count_only = false;
|
||||
bool files_only = false;
|
||||
bool recurse = false;
|
||||
bool regularexs = true;
|
||||
bool words_only = false;
|
||||
bool verbose = false;
|
||||
|
||||
|
||||
void usage()
|
||||
{
|
||||
std::cout <<
|
||||
"jgrep version 0.95\n"
|
||||
"usage: jgrep [-options] expression file [files...]\n"
|
||||
"\n"
|
||||
"options can be one of the following:\n"
|
||||
"\n"
|
||||
"-c prints a count of the number of matching lines only\n"
|
||||
"-d recurses through subdirectories for matching files\n"
|
||||
"-i causes case to be ignored when matching\n"
|
||||
"-l lists the files which contain a match only\n"
|
||||
"-n displays the line numbers of matches\n"
|
||||
"-r- causes the expression to be interpreted as a literal string and not\n"
|
||||
" as a regular expression\n"
|
||||
"-w searches for matches that are whole words only\n"
|
||||
"-z verbose mode\n"
|
||||
"\n"
|
||||
"expression: a regular expression, or a literal string if -r- is specified\n"
|
||||
"\n"
|
||||
"files: one or more files to search, the names can contain the wildcard\n"
|
||||
" characters ? and *\n" << std::endl;
|
||||
|
||||
}
|
||||
|
||||
void parse_switch(const char* flag)
|
||||
{
|
||||
++flag;
|
||||
while(*flag)
|
||||
{
|
||||
switch(*flag)
|
||||
{
|
||||
case '-':
|
||||
switch(*(flag-1))
|
||||
{
|
||||
case 'c':
|
||||
count_only = false;
|
||||
break;
|
||||
case 'd':
|
||||
recurse = false;
|
||||
break;
|
||||
case 'i':
|
||||
use_case = false;
|
||||
break;
|
||||
case 'l':
|
||||
files_only = false;
|
||||
break;
|
||||
case 'n':
|
||||
show_lines = false;
|
||||
break;
|
||||
case 'r':
|
||||
regularexs = false;
|
||||
break;
|
||||
case 'w':
|
||||
words_only = false;
|
||||
break;
|
||||
case 'z':
|
||||
verbose = false;
|
||||
break;
|
||||
default:
|
||||
std::cout << "Undefined option -";
|
||||
std::cout.put(*flag);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
// turn off prev character:
|
||||
break;
|
||||
case 'c':
|
||||
count_only = true;
|
||||
break;
|
||||
case 'd':
|
||||
recurse = true;
|
||||
break;
|
||||
case 'i':
|
||||
use_case = false;
|
||||
break;
|
||||
case 'l':
|
||||
files_only = true;
|
||||
break;
|
||||
case 'n':
|
||||
show_lines = true;
|
||||
break;
|
||||
case 'r':
|
||||
regularexs = true;
|
||||
break;
|
||||
case 'w':
|
||||
words_only = true;
|
||||
break;
|
||||
case 'z':
|
||||
verbose = true;
|
||||
break;
|
||||
case '?':
|
||||
usage();
|
||||
exit(0);
|
||||
case '+':
|
||||
break;
|
||||
default:
|
||||
std::cout << "Undefined option -";
|
||||
std::cout.put(*flag);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
++flag;
|
||||
}
|
||||
}
|
||||
|
||||
using namespace boost;
|
||||
|
||||
void HandleFile(const char* wild)
|
||||
{
|
||||
using namespace boost;
|
||||
file_iterator end;
|
||||
file_iterator start(wild);
|
||||
|
||||
if(recurse)
|
||||
{
|
||||
// go through sub directories:
|
||||
char buf[MAX_PATH];
|
||||
std::strcpy(buf, start.root());
|
||||
int rootlen = strlen(buf);
|
||||
if(*buf == 0)
|
||||
{
|
||||
std::strcpy(buf, ".");
|
||||
std::strcat(buf, directory_iterator::separator());
|
||||
std::strcat(buf, "*");
|
||||
}
|
||||
else
|
||||
{
|
||||
std::strcat(buf, directory_iterator::separator());
|
||||
std::strcat(buf, "*");
|
||||
}
|
||||
directory_iterator dstart(buf);
|
||||
directory_iterator dend;
|
||||
|
||||
// now get the file mask bit of "wild":
|
||||
const char* ptr = wild + rootlen;
|
||||
if(*ptr) ++ptr;
|
||||
|
||||
while(dstart != dend)
|
||||
{
|
||||
std::sprintf(buf, "%s%s%s", dstart.path(), directory_iterator::separator(), ptr);
|
||||
HandleFile(buf);
|
||||
++dstart;
|
||||
}
|
||||
}
|
||||
std::for_each(start, end, process_grep);
|
||||
}
|
||||
|
||||
int done = 0;
|
||||
|
||||
void HandleArg(const char* arg)
|
||||
{
|
||||
using namespace boost;
|
||||
if(*arg == '-')
|
||||
{
|
||||
parse_switch(arg);
|
||||
return;
|
||||
}
|
||||
if(done == 0)
|
||||
{
|
||||
// parse regular expression
|
||||
if(regularexs)
|
||||
{
|
||||
if(words_only == 0)
|
||||
{
|
||||
e.set_expression(arg, use_case ? regex::normal : regbase::normal | regbase::icase);
|
||||
//ei.set_expression(arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
char* buf = new char[std::strlen(arg) + 8];
|
||||
std::sprintf(buf, "\\<%s\\>", arg);
|
||||
e.set_expression(buf, use_case ? regex::normal : regbase::normal | regbase::icase);
|
||||
//ei.set_expression(buf);
|
||||
delete[] buf;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// we need to convert text to literal:
|
||||
int len2 = std::strlen(arg);
|
||||
int len = len2 * 5 + 6;
|
||||
char buf[8];
|
||||
char* buf2 = new char[len];
|
||||
*buf2 = 0;
|
||||
if(words_only)
|
||||
std::strcpy(buf2, "\\<");
|
||||
for(int j = 0; j < len2; ++j)
|
||||
{
|
||||
std::sprintf(buf, "\\0%o", int(arg[j]));
|
||||
std::strcat(buf2, buf);
|
||||
}
|
||||
if(words_only)
|
||||
std::strcat(buf2, "\\>");
|
||||
e.set_expression(buf2, use_case ? regex::normal : regbase::normal | regbase::icase);
|
||||
//ei.set_expression(buf2);
|
||||
delete[] buf2;
|
||||
}
|
||||
done = 1;
|
||||
return;
|
||||
}
|
||||
// if we get to here we have one or more file names to process:
|
||||
++done;
|
||||
HandleFile(arg);
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
for(int i = 1; i < argc; ++i)
|
||||
HandleArg(argv[i]);
|
||||
if(done < 2)
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <iostream>
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
std::std::cout <<
|
||||
"\n<note>\n"
|
||||
"This functionality is not available on with this compiler on this platform.\n"
|
||||
"</note>\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,18 +0,0 @@
|
||||
|
||||
#
|
||||
# very simple makefile for Visual C++ 6 + STLPort 4
|
||||
#
|
||||
|
||||
jgrep.exe: main.cpp jgrep.cpp jgrep.h
|
||||
cl -GX -GR /Oityb1 /GF /Gy -MT -I..\..\..\..\ jgrep.cpp main.cpp /link /LIBPATH:..\..\build\vc6-stlport user32.lib
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,18 +0,0 @@
|
||||
|
||||
#
|
||||
# very simple makefile for Visual C++ 6
|
||||
#
|
||||
|
||||
jgrep.exe: main.cpp jgrep.cpp jgrep.h
|
||||
cl -GX -GR /Oityb1 /GF /Gy -I..\..\..\..\ jgrep.cpp main.cpp /link /LIBPATH:..\..\build\vc6
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -30,4 +30,3 @@
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -31,3 +31,5 @@
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
@ -138,6 +138,8 @@ void test_sets()
|
||||
}
|
||||
|
||||
void test_sets2b();
|
||||
void test_sets2c();
|
||||
|
||||
void test_sets2()
|
||||
{
|
||||
using namespace boost::regex_constants;
|
||||
@ -245,7 +247,12 @@ void test_sets2()
|
||||
TEST_REGEX_SEARCH("[\\s]+", perl, "AB AB", match_default, make_array(2, 5, -2, -2));
|
||||
TEST_INVALID_REGEX("[\\S]", perl);
|
||||
TEST_REGEX_SEARCH("\\S+", perl, " abc ", match_default, make_array(2, 5, -2, -2));
|
||||
test_sets2c();
|
||||
}
|
||||
|
||||
void test_sets2c()
|
||||
{
|
||||
using namespace boost::regex_constants;
|
||||
// and some Perl style properties:
|
||||
TEST_REGEX_SEARCH("\\pl+", perl, "ABabcAB", match_default, make_array(2, 5, -2, -2));
|
||||
TEST_REGEX_SEARCH("\\Pl+", perl, "abABCab", match_default, make_array(2, 5, -2, -2));
|
||||
|
Reference in New Issue
Block a user