mirror of
https://github.com/tstack/lnav.git
synced 2024-08-16 16:30:25 +03:00
Some more sequence matching stuff.
This commit is contained in:
parent
e3d2d41aba
commit
44e8abc593
@ -47,6 +47,7 @@ noinst_HEADERS = \
|
|||||||
auto_temp_file.hh \
|
auto_temp_file.hh \
|
||||||
bookmarks.hh \
|
bookmarks.hh \
|
||||||
bottom_status_source.hh \
|
bottom_status_source.hh \
|
||||||
|
byte_array.hh \
|
||||||
db_sub_source.hh \
|
db_sub_source.hh \
|
||||||
grep_proc.hh \
|
grep_proc.hh \
|
||||||
help.hh \
|
help.hh \
|
||||||
@ -61,6 +62,8 @@ noinst_HEADERS = \
|
|||||||
pcrepp.hh \
|
pcrepp.hh \
|
||||||
piper_proc.hh \
|
piper_proc.hh \
|
||||||
readline_curses.hh \
|
readline_curses.hh \
|
||||||
|
sequence_matcher.hh \
|
||||||
|
sequence_sink.hh \
|
||||||
statusview_curses.hh \
|
statusview_curses.hh \
|
||||||
strong_int.hh \
|
strong_int.hh \
|
||||||
termios_guard.hh \
|
termios_guard.hh \
|
||||||
@ -83,6 +86,7 @@ libdiag_a_SOURCES = \
|
|||||||
logfile.cc \
|
logfile.cc \
|
||||||
logfile_sub_source.cc \
|
logfile_sub_source.cc \
|
||||||
readline_curses.cc \
|
readline_curses.cc \
|
||||||
|
sequence_matcher.cc \
|
||||||
statusview_curses.cc \
|
statusview_curses.cc \
|
||||||
piper_proc.cc \
|
piper_proc.cc \
|
||||||
textview_curses.cc \
|
textview_curses.cc \
|
||||||
|
@ -55,10 +55,10 @@ am_libdiag_a_OBJECTS = bookmarks.$(OBJEXT) grep_proc.$(OBJEXT) \
|
|||||||
hist_source.$(OBJEXT) line_buffer.$(OBJEXT) \
|
hist_source.$(OBJEXT) line_buffer.$(OBJEXT) \
|
||||||
listview_curses.$(OBJEXT) log_format.$(OBJEXT) \
|
listview_curses.$(OBJEXT) log_format.$(OBJEXT) \
|
||||||
logfile.$(OBJEXT) logfile_sub_source.$(OBJEXT) \
|
logfile.$(OBJEXT) logfile_sub_source.$(OBJEXT) \
|
||||||
readline_curses.$(OBJEXT) statusview_curses.$(OBJEXT) \
|
readline_curses.$(OBJEXT) sequence_matcher.$(OBJEXT) \
|
||||||
piper_proc.$(OBJEXT) textview_curses.$(OBJEXT) \
|
statusview_curses.$(OBJEXT) piper_proc.$(OBJEXT) \
|
||||||
view_curses.$(OBJEXT) vt52_curses.$(OBJEXT) \
|
textview_curses.$(OBJEXT) view_curses.$(OBJEXT) \
|
||||||
log_vtab_impl.$(OBJEXT)
|
vt52_curses.$(OBJEXT) log_vtab_impl.$(OBJEXT)
|
||||||
libdiag_a_OBJECTS = $(am_libdiag_a_OBJECTS)
|
libdiag_a_OBJECTS = $(am_libdiag_a_OBJECTS)
|
||||||
am__installdirs = "$(DESTDIR)$(bindir)"
|
am__installdirs = "$(DESTDIR)$(bindir)"
|
||||||
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
|
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
|
||||||
@ -229,6 +229,7 @@ noinst_HEADERS = \
|
|||||||
auto_temp_file.hh \
|
auto_temp_file.hh \
|
||||||
bookmarks.hh \
|
bookmarks.hh \
|
||||||
bottom_status_source.hh \
|
bottom_status_source.hh \
|
||||||
|
byte_array.hh \
|
||||||
db_sub_source.hh \
|
db_sub_source.hh \
|
||||||
grep_proc.hh \
|
grep_proc.hh \
|
||||||
help.hh \
|
help.hh \
|
||||||
@ -243,6 +244,8 @@ noinst_HEADERS = \
|
|||||||
pcrepp.hh \
|
pcrepp.hh \
|
||||||
piper_proc.hh \
|
piper_proc.hh \
|
||||||
readline_curses.hh \
|
readline_curses.hh \
|
||||||
|
sequence_matcher.hh \
|
||||||
|
sequence_sink.hh \
|
||||||
statusview_curses.hh \
|
statusview_curses.hh \
|
||||||
strong_int.hh \
|
strong_int.hh \
|
||||||
termios_guard.hh \
|
termios_guard.hh \
|
||||||
@ -265,6 +268,7 @@ libdiag_a_SOURCES = \
|
|||||||
logfile.cc \
|
logfile.cc \
|
||||||
logfile_sub_source.cc \
|
logfile_sub_source.cc \
|
||||||
readline_curses.cc \
|
readline_curses.cc \
|
||||||
|
sequence_matcher.cc \
|
||||||
statusview_curses.cc \
|
statusview_curses.cc \
|
||||||
piper_proc.cc \
|
piper_proc.cc \
|
||||||
textview_curses.cc \
|
textview_curses.cc \
|
||||||
@ -380,6 +384,7 @@ distclean-compile:
|
|||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logfile_sub_source.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logfile_sub_source.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/piper_proc.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/piper_proc.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readline_curses.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readline_curses.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sequence_matcher.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/statusview_curses.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/statusview_curses.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/textview_curses.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/textview_curses.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/view_curses.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/view_curses.Po@am__quote@
|
||||||
|
23
src/byte_array.hh
Normal file
23
src/byte_array.hh
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
|
||||||
|
#ifndef __byte_array_hh
|
||||||
|
#define __byte_array_hh
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
template<size_t BYTE_COUNT>
|
||||||
|
struct byte_array {
|
||||||
|
byte_array() { };
|
||||||
|
|
||||||
|
byte_array(const byte_array &other) {
|
||||||
|
memcpy(this->ba_data, other.ba_data, BYTE_COUNT);
|
||||||
|
};
|
||||||
|
|
||||||
|
bool operator<(const byte_array &other) const {
|
||||||
|
return memcmp(this->ba_data, other.ba_data, BYTE_COUNT) < 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned char ba_data[BYTE_COUNT];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -25,6 +25,7 @@ grep_proc::grep_proc(pcre *code,
|
|||||||
int &maxfd,
|
int &maxfd,
|
||||||
fd_set &readfds)
|
fd_set &readfds)
|
||||||
: gp_pcre(code),
|
: gp_pcre(code),
|
||||||
|
gp_code(code),
|
||||||
gp_source(gps),
|
gp_source(gps),
|
||||||
gp_pipe_offset(0),
|
gp_pipe_offset(0),
|
||||||
gp_child(-1),
|
gp_child(-1),
|
||||||
@ -167,25 +168,23 @@ void grep_proc::start(void)
|
|||||||
m = pc.all();
|
m = pc.all();
|
||||||
fprintf(stdout, "[%d:%d]\n", m->c_begin, m->c_end);
|
fprintf(stdout, "[%d:%d]\n", m->c_begin, m->c_end);
|
||||||
for (pc_iter = pc.begin(); pc_iter != pc.end(); pc_iter++) {
|
for (pc_iter = pc.begin(); pc_iter != pc.end(); pc_iter++) {
|
||||||
if (pc_iter->c_begin < 0) {
|
|
||||||
/* If the capture was conditional, pcre will
|
|
||||||
* return a -1 here.
|
|
||||||
*/
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stdout,
|
fprintf(stdout,
|
||||||
"(%d:%d)",
|
"(%d:%d)",
|
||||||
pc_iter->c_begin,
|
pc_iter->c_begin,
|
||||||
pc_iter->c_end);
|
pc_iter->c_end);
|
||||||
fwrite(pi.get_substr_start(pc_iter),
|
/* If the capture was conditional, pcre will return a -1
|
||||||
1,
|
* here.
|
||||||
pc_iter->length(),
|
*/
|
||||||
stdout);
|
if (pc_iter->c_begin >= 0) {
|
||||||
|
fwrite(pi.get_substr_start(pc_iter),
|
||||||
|
1,
|
||||||
|
pc_iter->length(),
|
||||||
|
stdout);
|
||||||
|
}
|
||||||
fputc('\n', stdout);
|
fputc('\n', stdout);
|
||||||
}
|
}
|
||||||
|
fprintf(stdout, "/\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((line + 1) % 10000) == 0) {
|
if (((line + 1) % 10000) == 0) {
|
||||||
@ -259,16 +258,22 @@ void grep_proc::dispatch_line(char *line)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (sscanf(line, "(%d:%d)%n", &start, &end, &capture_start) == 2) {
|
else if (sscanf(line, "(%d:%d)%n", &start, &end, &capture_start) == 2) {
|
||||||
assert(start >= 0);
|
assert(start == -1 || start >= 0);
|
||||||
assert(end >= 0);
|
assert(end >= 0);
|
||||||
|
|
||||||
/* Pass the match offsets to the sink delegate. */
|
/* Pass the captured strings to the sink delegate. */
|
||||||
if (this->gp_sink != NULL) {
|
if (this->gp_sink != NULL) {
|
||||||
this->gp_sink->grep_capture(*this,
|
this->gp_sink->grep_capture(*this,
|
||||||
this->gp_last_line,
|
this->gp_last_line,
|
||||||
start,
|
start,
|
||||||
end,
|
end,
|
||||||
&line[capture_start]);
|
start < 0 ?
|
||||||
|
NULL : &line[capture_start]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (line[0] == '/') {
|
||||||
|
if (this->gp_sink != NULL) {
|
||||||
|
this->gp_sink->grep_match_end(*this, this->gp_last_line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -102,6 +102,8 @@ public:
|
|||||||
int start,
|
int start,
|
||||||
int end,
|
int end,
|
||||||
char *capture) { };
|
char *capture) { };
|
||||||
|
|
||||||
|
virtual void grep_match_end(grep_proc &gp, grep_line_t line) { };
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -126,10 +128,8 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a grep_proc object. This involves compiling the regular
|
* Construct a grep_proc object. You must call the start() method
|
||||||
* expression and then forking off the child process. Note that both the
|
* to fork off the child process and begin processing.
|
||||||
* parent and child return from this call and you must call the start()
|
|
||||||
* method immediately afterward to get things going.
|
|
||||||
*
|
*
|
||||||
* @param code The pcre code to run over the lines of input.
|
* @param code The pcre code to run over the lines of input.
|
||||||
* @param gps The source of the data to match.
|
* @param gps The source of the data to match.
|
||||||
|
@ -195,7 +195,8 @@ public:
|
|||||||
this->gr_highlighter->get_role(this->gr_next_field);
|
this->gr_highlighter->get_role(this->gr_next_field);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sscanf(capture, "%f", &amount);
|
if (capture != 0)
|
||||||
|
sscanf(capture, "%f", &amount);
|
||||||
this->add_value(this->gr_x, this->gr_next_field, amount);
|
this->add_value(this->gr_x, this->gr_next_field, amount);
|
||||||
|
|
||||||
++ this->gr_next_field;
|
++ this->gr_next_field;
|
||||||
|
52
src/sequence_matcher.cc
Normal file
52
src/sequence_matcher.cc
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <openssl/sha.h>
|
||||||
|
|
||||||
|
#include "sequence_matcher.hh"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
sequence_matcher::sequence_matcher(field_col_t &example)
|
||||||
|
{
|
||||||
|
for (field_col_t::iterator col_iter = example.begin();
|
||||||
|
col_iter != example.end();
|
||||||
|
++col_iter) {
|
||||||
|
std::string first_value;
|
||||||
|
field sf;
|
||||||
|
|
||||||
|
sf.sf_value = *col_iter;
|
||||||
|
for (field_row_t::iterator row_iter = (*col_iter).begin();
|
||||||
|
row_iter != (*col_iter).end();
|
||||||
|
++row_iter) {
|
||||||
|
if (row_iter == (*col_iter).begin()) {
|
||||||
|
first_value = *row_iter;
|
||||||
|
}
|
||||||
|
else if (first_value != *row_iter) {
|
||||||
|
sf.sf_type = FT_CONSTANT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sf.sf_type == FT_VARIABLE)
|
||||||
|
sf.sf_value.clear();
|
||||||
|
this->sm_fields.push_back(sf);
|
||||||
|
}
|
||||||
|
this->sm_count = example.front().size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void sequence_matcher::identity(const std::vector<string> &values, id_t &id_out)
|
||||||
|
{
|
||||||
|
SHA_CTX context;
|
||||||
|
int lpc = 0;
|
||||||
|
|
||||||
|
SHA_Init(&context);
|
||||||
|
for (std::list<field>::iterator iter = sm_fields.begin();
|
||||||
|
iter != sm_fields.end();
|
||||||
|
++iter, lpc++) {
|
||||||
|
if (iter->sf_type == FT_VARIABLE) {
|
||||||
|
SHA_Update(&context,
|
||||||
|
values[lpc].c_str(),
|
||||||
|
values[lpc].length() + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SHA_Final(id_out.ba_data, &context);
|
||||||
|
}
|
76
src/sequence_matcher.hh
Normal file
76
src/sequence_matcher.hh
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
|
||||||
|
#ifndef __sequence_matcher_hh
|
||||||
|
#define __sequence_matcher_hh
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "byte_array.hh"
|
||||||
|
|
||||||
|
class sequence_matcher {
|
||||||
|
public:
|
||||||
|
typedef std::vector<std::string> field_row_t;
|
||||||
|
typedef std::list<field_row_t> field_col_t;
|
||||||
|
|
||||||
|
typedef byte_array<20> id_t;
|
||||||
|
|
||||||
|
enum field_type_t {
|
||||||
|
FT_VARIABLE,
|
||||||
|
FT_CONSTANT,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct field {
|
||||||
|
|
||||||
|
public:
|
||||||
|
field() : sf_type(FT_VARIABLE) { };
|
||||||
|
|
||||||
|
field_type_t sf_type;
|
||||||
|
field_row_t sf_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
sequence_matcher(field_col_t &example);
|
||||||
|
|
||||||
|
void identity(const std::vector<std::string> &values, id_t &id_out);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
bool match(const std::vector<std::string> &values,
|
||||||
|
std::vector<T> &state,
|
||||||
|
T index) {
|
||||||
|
bool index_match = true;
|
||||||
|
int lpc = 0;
|
||||||
|
|
||||||
|
retry:
|
||||||
|
for (std::list<field>::iterator iter = this->sm_fields.begin();
|
||||||
|
iter != this->sm_fields.end();
|
||||||
|
++iter, lpc++) {
|
||||||
|
if (iter->sf_type != sequence_matcher::FT_CONSTANT) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iter->sf_value[state.size()] != values[lpc]) {
|
||||||
|
if (state.size() > 0) {
|
||||||
|
state.clear();
|
||||||
|
lpc = 0;
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
index_match = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index_match) {
|
||||||
|
state.push_back(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (this->sm_count == state.size());
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
int sm_count;
|
||||||
|
std::list<field> sm_fields;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
63
src/sequence_sink.hh
Normal file
63
src/sequence_sink.hh
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
|
||||||
|
#ifndef __sequence_sink_hh
|
||||||
|
#define __sequence_sink_hh
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include "bookmarks.hh"
|
||||||
|
#include "grep_proc.hh"
|
||||||
|
#include "sequence_matcher.hh"
|
||||||
|
|
||||||
|
class sequence_sink : public grep_proc_sink {
|
||||||
|
public:
|
||||||
|
sequence_sink(sequence_matcher &sm, bookmark_vector &bv) :
|
||||||
|
ss_matcher(sm),
|
||||||
|
ss_bookmarks(bv) {
|
||||||
|
};
|
||||||
|
|
||||||
|
void grep_match(grep_proc &gp,
|
||||||
|
grep_line_t line,
|
||||||
|
int start,
|
||||||
|
int end) {
|
||||||
|
this->ss_line_values.clear();
|
||||||
|
};
|
||||||
|
|
||||||
|
void grep_capture(grep_proc &gp,
|
||||||
|
grep_line_t line,
|
||||||
|
int start,
|
||||||
|
int end,
|
||||||
|
char *capture) {
|
||||||
|
if (start == -1)
|
||||||
|
this->ss_line_values.push_back("");
|
||||||
|
else
|
||||||
|
this->ss_line_values.push_back(std::string(capture));
|
||||||
|
};
|
||||||
|
|
||||||
|
void grep_match_end(grep_proc &gp, grep_line_t line) {
|
||||||
|
sequence_matcher::id_t line_id;
|
||||||
|
|
||||||
|
this->ss_matcher.identity(this->ss_line_values, line_id);
|
||||||
|
|
||||||
|
std::vector<grep_line_t> &line_state = this->ss_state[line_id];
|
||||||
|
if (this->ss_matcher.match(this->ss_line_values,
|
||||||
|
line_state,
|
||||||
|
line)) {
|
||||||
|
std::vector<grep_line_t>::iterator iter;
|
||||||
|
|
||||||
|
for (iter = line_state.begin();
|
||||||
|
iter != line_state.end();
|
||||||
|
++iter) {
|
||||||
|
this->ss_bookmarks.insert_once(vis_line_t(*iter));
|
||||||
|
}
|
||||||
|
line_state.clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
sequence_matcher &ss_matcher;
|
||||||
|
bookmark_vector &ss_bookmarks;
|
||||||
|
std::vector<std::string> ss_line_values;
|
||||||
|
std::map< sequence_matcher::id_t, std::vector<grep_line_t> > ss_state;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -90,7 +90,9 @@ drive_sequencer_SOURCES = \
|
|||||||
../src/logfile.cc \
|
../src/logfile.cc \
|
||||||
../src/log_format.cc \
|
../src/log_format.cc \
|
||||||
../src/line_buffer.cc \
|
../src/line_buffer.cc \
|
||||||
|
../src/sequence_matcher.cc \
|
||||||
drive_sequencer.cc
|
drive_sequencer.cc
|
||||||
|
drive_sequencer_LDADD = -lcrypto
|
||||||
|
|
||||||
drive_vt52_curses_SOURCES = \
|
drive_vt52_curses_SOURCES = \
|
||||||
../src/vt52_curses.cc \
|
../src/vt52_curses.cc \
|
||||||
|
@ -83,9 +83,8 @@ drive_readline_curses_DEPENDENCIES = $(am__DEPENDENCIES_1) \
|
|||||||
$(am__DEPENDENCIES_1)
|
$(am__DEPENDENCIES_1)
|
||||||
am_drive_sequencer_OBJECTS = grep_proc.$(OBJEXT) logfile.$(OBJEXT) \
|
am_drive_sequencer_OBJECTS = grep_proc.$(OBJEXT) logfile.$(OBJEXT) \
|
||||||
log_format.$(OBJEXT) line_buffer.$(OBJEXT) \
|
log_format.$(OBJEXT) line_buffer.$(OBJEXT) \
|
||||||
drive_sequencer.$(OBJEXT)
|
sequence_matcher.$(OBJEXT) drive_sequencer.$(OBJEXT)
|
||||||
drive_sequencer_OBJECTS = $(am_drive_sequencer_OBJECTS)
|
drive_sequencer_OBJECTS = $(am_drive_sequencer_OBJECTS)
|
||||||
drive_sequencer_LDADD = $(LDADD)
|
|
||||||
drive_sequencer_DEPENDENCIES =
|
drive_sequencer_DEPENDENCIES =
|
||||||
am_drive_vt52_curses_OBJECTS = vt52_curses.$(OBJEXT) \
|
am_drive_vt52_curses_OBJECTS = vt52_curses.$(OBJEXT) \
|
||||||
drive_vt52_curses.$(OBJEXT)
|
drive_vt52_curses.$(OBJEXT)
|
||||||
@ -338,8 +337,10 @@ drive_sequencer_SOURCES = \
|
|||||||
../src/logfile.cc \
|
../src/logfile.cc \
|
||||||
../src/log_format.cc \
|
../src/log_format.cc \
|
||||||
../src/line_buffer.cc \
|
../src/line_buffer.cc \
|
||||||
|
../src/sequence_matcher.cc \
|
||||||
drive_sequencer.cc
|
drive_sequencer.cc
|
||||||
|
|
||||||
|
drive_sequencer_LDADD = -lcrypto
|
||||||
drive_vt52_curses_SOURCES = \
|
drive_vt52_curses_SOURCES = \
|
||||||
../src/vt52_curses.cc \
|
../src/vt52_curses.cc \
|
||||||
drive_vt52_curses.cc
|
drive_vt52_curses.cc
|
||||||
@ -495,6 +496,7 @@ distclean-compile:
|
|||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logfile_sub_source.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logfile_sub_source.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readline_curses.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readline_curses.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scripty.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scripty.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sequence_matcher.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/slicer.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/slicer.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_auto_fd.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_auto_fd.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_auto_mem.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_auto_mem.Po@am__quote@
|
||||||
@ -633,6 +635,20 @@ readline_curses.obj: ../src/readline_curses.cc
|
|||||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o readline_curses.obj `if test -f '../src/readline_curses.cc'; then $(CYGPATH_W) '../src/readline_curses.cc'; else $(CYGPATH_W) '$(srcdir)/../src/readline_curses.cc'; fi`
|
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o readline_curses.obj `if test -f '../src/readline_curses.cc'; then $(CYGPATH_W) '../src/readline_curses.cc'; else $(CYGPATH_W) '$(srcdir)/../src/readline_curses.cc'; fi`
|
||||||
|
|
||||||
|
sequence_matcher.o: ../src/sequence_matcher.cc
|
||||||
|
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT sequence_matcher.o -MD -MP -MF $(DEPDIR)/sequence_matcher.Tpo -c -o sequence_matcher.o `test -f '../src/sequence_matcher.cc' || echo '$(srcdir)/'`../src/sequence_matcher.cc
|
||||||
|
@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/sequence_matcher.Tpo $(DEPDIR)/sequence_matcher.Po
|
||||||
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../src/sequence_matcher.cc' object='sequence_matcher.o' libtool=no @AMDEPBACKSLASH@
|
||||||
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
|
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o sequence_matcher.o `test -f '../src/sequence_matcher.cc' || echo '$(srcdir)/'`../src/sequence_matcher.cc
|
||||||
|
|
||||||
|
sequence_matcher.obj: ../src/sequence_matcher.cc
|
||||||
|
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT sequence_matcher.obj -MD -MP -MF $(DEPDIR)/sequence_matcher.Tpo -c -o sequence_matcher.obj `if test -f '../src/sequence_matcher.cc'; then $(CYGPATH_W) '../src/sequence_matcher.cc'; else $(CYGPATH_W) '$(srcdir)/../src/sequence_matcher.cc'; fi`
|
||||||
|
@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/sequence_matcher.Tpo $(DEPDIR)/sequence_matcher.Po
|
||||||
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../src/sequence_matcher.cc' object='sequence_matcher.obj' libtool=no @AMDEPBACKSLASH@
|
||||||
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
|
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o sequence_matcher.obj `if test -f '../src/sequence_matcher.cc'; then $(CYGPATH_W) '../src/sequence_matcher.cc'; else $(CYGPATH_W) '$(srcdir)/../src/sequence_matcher.cc'; fi`
|
||||||
|
|
||||||
bookmarks.o: ../src/bookmarks.cc
|
bookmarks.o: ../src/bookmarks.cc
|
||||||
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT bookmarks.o -MD -MP -MF $(DEPDIR)/bookmarks.Tpo -c -o bookmarks.o `test -f '../src/bookmarks.cc' || echo '$(srcdir)/'`../src/bookmarks.cc
|
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT bookmarks.o -MD -MP -MF $(DEPDIR)/bookmarks.Tpo -c -o bookmarks.o `test -f '../src/bookmarks.cc' || echo '$(srcdir)/'`../src/bookmarks.cc
|
||||||
@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/bookmarks.Tpo $(DEPDIR)/bookmarks.Po
|
@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/bookmarks.Tpo $(DEPDIR)/bookmarks.Po
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@ -18,123 +19,118 @@
|
|||||||
|
|
||||||
#include "pcrepp.hh"
|
#include "pcrepp.hh"
|
||||||
#include "logfile.hh"
|
#include "logfile.hh"
|
||||||
|
#include "sequence_sink.hh"
|
||||||
|
#include "sequence_matcher.hh"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
string in[] = {
|
class my_source : public grep_proc_source {
|
||||||
"eth0 up",
|
|
||||||
"eth0 down",
|
|
||||||
""
|
|
||||||
};
|
|
||||||
|
|
||||||
class sequence_source {
|
|
||||||
public:
|
|
||||||
virtual ~sequence_source() { };
|
|
||||||
|
|
||||||
virtual bool sequence_value_for_field(int line,
|
|
||||||
int col,
|
|
||||||
std::string &value_out) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<size_t BYTE_COUNT>
|
|
||||||
class byte_array {
|
|
||||||
public:
|
|
||||||
|
|
||||||
bool operator<(const byte_array &other) const {
|
|
||||||
return memcmp(this->ba_data, other.ba_data, BYTE_COUNT) < 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned char ba_data[BYTE_COUNT];
|
|
||||||
};
|
|
||||||
|
|
||||||
class sequence_matcher {
|
|
||||||
public:
|
public:
|
||||||
typedef std::vector<string> field_row_t;
|
my_source(auto_fd &fd) : ms_offset(0) {
|
||||||
typedef std::list<field_row_t> field_col_t;
|
this->ms_buffer.set_fd(fd);
|
||||||
|
|
||||||
enum field_type_t {
|
|
||||||
FT_VARIABLE,
|
|
||||||
FT_CONSTANT,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class state<T> {
|
bool grep_value_for_line(int line_number, string &value_out) {
|
||||||
public:
|
bool retval = false;
|
||||||
std::vector<T> sms_line;
|
|
||||||
|
|
||||||
byte_array<20> sms_id;
|
try {
|
||||||
};
|
size_t len;
|
||||||
|
char *line;
|
||||||
class field {
|
|
||||||
|
|
||||||
public:
|
|
||||||
field() : sf_type(FT_VARIABLE) { };
|
|
||||||
|
|
||||||
field_type_t sf_type;
|
|
||||||
field_col_t sf_value;
|
|
||||||
};
|
|
||||||
|
|
||||||
sequence_matcher(field_col_t example) {
|
|
||||||
for (field_col_t::iterator col_iter = example.begin();
|
|
||||||
col_iter != example.end();
|
|
||||||
++col_iter) {
|
|
||||||
std::string first_value;
|
|
||||||
|
|
||||||
for (field_row_t::iterator row_iter = (*col_iter).begin();
|
if ((line = this->ms_buffer.read_line(this->ms_offset,
|
||||||
row_iter != (*col_iter).end();
|
len)) != NULL) {
|
||||||
++row_iter) {
|
value_out = string(line, len);
|
||||||
if (row_iter == (*col_iter).begin()) {
|
retval = true;
|
||||||
first_value = *row_iter;
|
|
||||||
}
|
|
||||||
else if (first_value != *row_iter) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (line_buffer::error &e) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"error: source buffer error %d %s\n",
|
||||||
|
this->ms_buffer.get_fd(),
|
||||||
|
strerror(e.e_err));
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
line_buffer ms_buffer;
|
||||||
|
off_t ms_offset;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int c, retval = EXIT_SUCCESS;
|
int c, retval = EXIT_SUCCESS;
|
||||||
|
const char *errptr;
|
||||||
|
auto_fd fd;
|
||||||
|
pcre *code;
|
||||||
|
int eoff;
|
||||||
|
|
||||||
|
if (argc < 3) {
|
||||||
|
fprintf(stderr, "error: expecting pattern and file arguments\n");
|
||||||
|
retval = EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
else if ((fd = open(argv[2], O_RDONLY)) == -1) {
|
||||||
|
perror("open");
|
||||||
|
retval = EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
else if ((code = pcre_compile(argv[1],
|
||||||
|
PCRE_CASELESS,
|
||||||
|
&errptr,
|
||||||
|
&eoff,
|
||||||
|
NULL)) == NULL) {
|
||||||
|
fprintf(stderr, "error: invalid pattern -- %s\n", errptr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
my_source ms(fd);
|
||||||
|
fd_set read_fds;
|
||||||
|
int maxfd;
|
||||||
|
|
||||||
pcre_context_static<20> *captures = new pcre_context_static<20>[2];
|
sequence_matcher::field_col_t fc;
|
||||||
long cols = 0;
|
|
||||||
|
fc.resize(2);
|
||||||
|
|
||||||
|
sequence_matcher::field_row_t &frf = fc.front();
|
||||||
|
frf.resize(2);
|
||||||
|
frf[0] = "eth0";
|
||||||
|
frf[1] = "eth0";
|
||||||
|
|
||||||
|
sequence_matcher::field_row_t &frb = fc.back();
|
||||||
|
frb.resize(2);
|
||||||
|
frb[0] = "up";
|
||||||
|
frb[1] = "down";
|
||||||
|
|
||||||
sequence::field *fields = new sequence::field[2];
|
static bookmark_type_t SEQUENCE;
|
||||||
|
|
||||||
pcrepp re("(\\w+) (up|down)");
|
sequence_matcher sm(fc);
|
||||||
|
bookmarks bm;
|
||||||
|
sequence_sink ss(sm, bm[&SEQUENCE]);
|
||||||
|
|
||||||
|
FD_ZERO(&read_fds);
|
||||||
|
|
||||||
|
grep_proc gp(code, ms, maxfd, read_fds);
|
||||||
|
|
||||||
|
gp.queue_request();
|
||||||
|
gp.start();
|
||||||
|
gp.set_sink(&ss);
|
||||||
|
|
||||||
for (int lpc = 0; in[lpc] != ""; lpc++) {
|
while (bm[&SEQUENCE].size() == 0) {
|
||||||
pcre_input pi(in[lpc]);
|
fd_set rfds = read_fds;
|
||||||
bool rc;
|
|
||||||
|
select(maxfd + 1, &rfds, NULL, NULL, NULL);
|
||||||
rc = re.match(captures[lpc], pi);
|
|
||||||
cols = max(cols, captures[lpc].end() - captures[lpc].begin());
|
|
||||||
|
|
||||||
assert(rc);
|
gp.check_fd_set(rfds);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int curr_col = 0; curr_col < cols; curr_col++) {
|
for (bookmark_vector::iterator iter = bm[&SEQUENCE].begin();
|
||||||
string first_row;
|
iter != bm[&SEQUENCE].end();
|
||||||
|
++iter) {
|
||||||
for (int curr_row = 0; curr_row < 2; curr_row++) {
|
printf("%d\n", (const int)*iter);
|
||||||
pcre_input pi(in[curr_row]);
|
}
|
||||||
string curr = pi.get_substr(captures[curr_col].begin() + curr_col);
|
}
|
||||||
|
|
||||||
if (curr_row == 0) {
|
return retval;
|
||||||
first_row = curr;
|
|
||||||
}
|
|
||||||
else if (first_row != curr) {
|
|
||||||
fields[curr_col].sf_type = sequence::FT_CONSTANT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int lpc = 0; lpc < cols; lpc++) {
|
|
||||||
printf("field[%d] = %d\n", lpc, fields[lpc].sf_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
3
test/logfile_syslog.2
Normal file
3
test/logfile_syslog.2
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
Nov 3 09:23:38 veridian foo[7998]: eth0 is up
|
||||||
|
Nov 3 09:23:38 veridian foo[16442]: eth1 is up
|
||||||
|
Nov 3 09:23:38 veridian foo[7999]: eth0 is down
|
Loading…
Reference in New Issue
Block a user