mirror of https://github.com/tstack/lnav
[cleanup] start a tracer/debugger for the data parser
parent
e71a85d471
commit
5d478fc17a
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Written by Alexey Tourbin <at@altlinux.org>.
|
||||
*
|
||||
* The author has dedicated the code to the public domain. Anyone is free
|
||||
* to copy, modify, publish, use, compile, sell, or distribute the original
|
||||
* code, either in source code form or as a compiled binary, for any purpose,
|
||||
* commercial or non-commercial, and by any means.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sqlite3.h>
|
||||
|
||||
#include "pcrepp.hh"
|
||||
|
||||
#include "sqlite-extension-func.h"
|
||||
|
||||
typedef struct {
|
||||
char *s;
|
||||
pcre *p;
|
||||
pcre_extra *e;
|
||||
} cache_entry;
|
||||
|
||||
#ifndef CACHE_SIZE
|
||||
#define CACHE_SIZE 16
|
||||
#endif
|
||||
|
||||
static
|
||||
void regexp(sqlite3_context *ctx, int argc, sqlite3_value **argv)
|
||||
{
|
||||
const char *re, *str;
|
||||
pcre *p;
|
||||
pcre_extra *e;
|
||||
|
||||
assert(argc == 2);
|
||||
|
||||
re = (const char *) sqlite3_value_text(argv[0]);
|
||||
if (!re) {
|
||||
sqlite3_result_error(ctx, "no regexp", -1);
|
||||
return;
|
||||
}
|
||||
|
||||
str = (const char *) sqlite3_value_text(argv[1]);
|
||||
if (!str) {
|
||||
sqlite3_result_error(ctx, "no string", -1);
|
||||
return;
|
||||
}
|
||||
|
||||
/* simple LRU cache */
|
||||
{
|
||||
static cache_entry cache[CACHE_SIZE];
|
||||
int i;
|
||||
int found = 0;
|
||||
|
||||
for (i = 0; i < CACHE_SIZE && cache[i].s; i++) {
|
||||
if (strcmp(re, cache[i].s) == 0) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
if (i > 0) {
|
||||
cache_entry c = cache[i];
|
||||
memmove(cache + 1, cache, i * sizeof(cache_entry));
|
||||
cache[0] = c;
|
||||
}
|
||||
}
|
||||
else {
|
||||
cache_entry c;
|
||||
const char *err;
|
||||
int pos;
|
||||
c.p = pcre_compile(re, 0, &err, &pos, NULL);
|
||||
if (!c.p) {
|
||||
char *e2 = sqlite3_mprintf("%s: %s (offset %d)", re, err, pos);
|
||||
sqlite3_result_error(ctx, e2, -1);
|
||||
sqlite3_free(e2);
|
||||
return;
|
||||
}
|
||||
c.e = pcre_study(c.p, 0, &err);
|
||||
c.s = strdup(re);
|
||||
if (!c.s) {
|
||||
sqlite3_result_error(ctx, "strdup: ENOMEM", -1);
|
||||
pcre_free(c.p);
|
||||
pcre_free(c.e);
|
||||
return;
|
||||
}
|
||||
i = CACHE_SIZE - 1;
|
||||
if (cache[i].s) {
|
||||
free(cache[i].s);
|
||||
assert(cache[i].p);
|
||||
pcre_free(cache[i].p);
|
||||
pcre_free(cache[i].e);
|
||||
}
|
||||
memmove(cache + 1, cache, i * sizeof(cache_entry));
|
||||
cache[0] = c;
|
||||
}
|
||||
p = cache[0].p;
|
||||
e = cache[0].e;
|
||||
}
|
||||
|
||||
{
|
||||
int rc;
|
||||
assert(p);
|
||||
rc = pcre_exec(p, e, str, strlen(str), 0, 0, NULL, 0);
|
||||
sqlite3_result_int(ctx, rc >= 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int string_extension_functions(const struct FuncDef **basic_funcs,
|
||||
const struct FuncDefAgg **agg_funcs)
|
||||
{
|
||||
static const struct FuncDef string_funcs[] = {
|
||||
{ "regexp", 2, 0, SQLITE_UTF8, 0, regexp },
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
*basic_funcs = string_funcs;
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
time_t time(time_t *loc)
|
||||
{
|
||||
time_t retval = 1370546000;
|
||||
|
||||
if (loc != NULL) {
|
||||
*loc = retval;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
2013-06-05T14:20:24 DEBUG cc2.main CC - 4672610200547811617359537811896212984085567168.114723023 Json_Reader - Doing prepare for resource name "Json_Reader", component "com.json.components.JSONReader"
|
||||
key 26:26 ^
|
||||
sym 26:34 ^------^ cc2.main
|
||||
pair 26:34 ^------^ cc2.main
|
||||
key 35:35 ^
|
||||
sym 35:37 ^^ CC
|
||||
pair 35:37 ^^ CC
|
||||
key 38:38 ^
|
||||
sym 38:39 ^ -
|
||||
pair 38:39 ^ -
|
||||
key 40:40 ^
|
||||
num 40:96 ^------------------------------------------------------^ 4672610200547811617359537811896212984085567168.114723023
|
||||
pair 40:96 ^------------------------------------------------------^ 4672610200547811617359537811896212984085567168.114723023
|
||||
key 97:97 ^
|
||||
sym 97:108 ^---------^ Json_Reader
|
||||
pair 97:108 ^---------^ Json_Reader
|
||||
key 109:109 ^
|
||||
sym 109:110 ^ -
|
||||
pair 109:110 ^ -
|
||||
key 144:144 ^
|
||||
quot 144:155 ^---------^ Json_Reader
|
||||
pair 144:155 ^---------^ Json_Reader
|
||||
key 169:169 ^
|
||||
quot 169:199 ^----------------------------^ com.json.components.JSONReader
|
||||
pair 169:199 ^----------------------------^ com.json.components.JSONReader
|
@ -0,0 +1,204 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
# Copyright (c) 2013, Timothy Stack
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice, this
|
||||
# list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Timothy Stack nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
|
||||
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import os
|
||||
import json
|
||||
import string
|
||||
import readline
|
||||
import itertools
|
||||
import collections
|
||||
|
||||
TEST_DIR = os.path.dirname(__file__)
|
||||
ROOT_DIR = os.path.dirname(TEST_DIR)
|
||||
SRC_DIR = os.path.join(ROOT_DIR, "src")
|
||||
|
||||
addr_to_name = {}
|
||||
name_to_addr = {}
|
||||
element_lists = collections.defaultdict(list)
|
||||
breakpoints = set()
|
||||
|
||||
def completer(text, state):
|
||||
options = [x for x in itertools.chain(name_to_addr,
|
||||
element_lists,
|
||||
breakpoints)
|
||||
if x.startswith(text)]
|
||||
try:
|
||||
return options[state]
|
||||
except IndexError:
|
||||
return None
|
||||
|
||||
readline.set_completer(completer)
|
||||
|
||||
if 'libedit' in readline.__doc__:
|
||||
readline.parse_and_bind('bind ^I rl_complete')
|
||||
else:
|
||||
readline.parse_and_bind('tab: complete')
|
||||
|
||||
input_line = ''
|
||||
ops = []
|
||||
for line in open("scanned.dpt"):
|
||||
if line.startswith("input "):
|
||||
input_line = line[6:-1]
|
||||
else:
|
||||
ops.append(map(string.strip, line.split()))
|
||||
|
||||
def getstr(capture):
|
||||
start, end = capture.split(':')
|
||||
return input_line[int(start):int(end)]
|
||||
|
||||
def printlist(name_or_addr):
|
||||
if name_or_addr in name_to_addr:
|
||||
print "(%s) %s" % (name_or_addr, element_lists[name_to_addr[name_or_addr]])
|
||||
elif name_or_addr in element_lists:
|
||||
print "(%s) %s" % (addr_to_name.get(name_or_addr, name_or_addr),
|
||||
element_lists[name_or_addr])
|
||||
else:
|
||||
print "error: unknown list --", name_or_addr
|
||||
|
||||
def handleop(fields):
|
||||
addr = fields[0]
|
||||
loc = fields[1].split(':')
|
||||
method_name = fields[2]
|
||||
method_args = fields[3:]
|
||||
|
||||
if addr == '0x0':
|
||||
el = None
|
||||
else:
|
||||
el = element_lists[addr]
|
||||
|
||||
if method_name == 'element_list_t':
|
||||
addr_to_name[addr] = method_args[0]
|
||||
name_to_addr[method_args[0]] = addr
|
||||
elif method_name == '~element_list_t':
|
||||
pass
|
||||
elif method_name == 'push_back':
|
||||
el.append((method_args[0], getstr(method_args[1])))
|
||||
elif method_name == 'pop_front':
|
||||
el.pop(0)
|
||||
elif method_name == 'pop_back':
|
||||
el.pop()
|
||||
elif method_name == 'splice':
|
||||
pos = int(method_args[0])
|
||||
other = element_lists[method_args[1]]
|
||||
start, from_end = map(int, method_args[2].split(':'))
|
||||
end = len(other) - from_end
|
||||
sub_list = other[start:end]
|
||||
del other[start:end]
|
||||
el[pos:pos] = sub_list
|
||||
elif method_name == 'point':
|
||||
breakpoints.add(method_args[0])
|
||||
else:
|
||||
print "Unhandled method: ", method_name
|
||||
|
||||
def playupto(length):
|
||||
addr_to_name.clear()
|
||||
name_to_addr.clear()
|
||||
element_lists.clear()
|
||||
for index in range(length):
|
||||
handleop(ops[index])
|
||||
|
||||
def find_prev_point(start, name):
|
||||
orig_start = start
|
||||
while start > 0:
|
||||
start -= 1;
|
||||
fields = ops[start]
|
||||
if fields[2] != 'point':
|
||||
continue
|
||||
if not name or fields[3] == name:
|
||||
return start + 1
|
||||
return orig_start + 1
|
||||
|
||||
def find_next_point(start, name):
|
||||
orig_start = start
|
||||
while start < len(ops):
|
||||
start += 1;
|
||||
fields = ops[start]
|
||||
if fields[2] != 'point':
|
||||
continue
|
||||
if not name or fields[3] == name:
|
||||
return start + 1
|
||||
return orig_start + 1
|
||||
|
||||
index = len(ops)
|
||||
last_cmd = ['']
|
||||
watch_list = set()
|
||||
while True:
|
||||
playupto(index)
|
||||
|
||||
if index == 0:
|
||||
print "init"
|
||||
else:
|
||||
print "#%s %s" % (index -1, ops[index - 1])
|
||||
|
||||
for list_name in watch_list:
|
||||
printlist(list_name)
|
||||
|
||||
try:
|
||||
cmd = raw_input("> ").split()
|
||||
except EOFError:
|
||||
print
|
||||
break
|
||||
|
||||
if not cmd or cmd[0] == '':
|
||||
cmd = last_cmd
|
||||
|
||||
if not cmd or cmd[0] == '':
|
||||
pass
|
||||
elif cmd[0] == 'q':
|
||||
break
|
||||
elif cmd[0] == 'n':
|
||||
if index < len(ops):
|
||||
index += 1
|
||||
elif cmd[0] == 'r':
|
||||
if index > 0:
|
||||
index -= 1
|
||||
elif cmd[0] == 'b':
|
||||
if len(cmd) == 1:
|
||||
cmd.append('')
|
||||
|
||||
index = find_prev_point(index - 1, cmd[1])
|
||||
elif cmd[0] == 'c':
|
||||
if len(cmd) == 1:
|
||||
cmd.append('')
|
||||
index = find_next_point(index - 1, cmd[1])
|
||||
elif cmd[0] == 'p':
|
||||
if len(cmd) > 1:
|
||||
printlist(cmd[1])
|
||||
else:
|
||||
print input_line
|
||||
for addr in element_lists:
|
||||
printlist(addr)
|
||||
elif cmd[0] == 'w':
|
||||
watch_list.add(cmd[1])
|
||||
elif cmd[0] == 'u':
|
||||
watch_list.remove(cmd[1])
|
||||
else:
|
||||
print "error: unknown command --", cmd
|
||||
|
||||
last_cmd = cmd
|
@ -0,0 +1,12 @@
|
||||
|
||||
CREATE TABLE IF NOT EXISTS person (
|
||||
id integer PRIMARY KEY,
|
||||
first_name text,
|
||||
last_name text,
|
||||
age integer
|
||||
);
|
||||
|
||||
INSERT INTO person (id, first_name, last_name, age)
|
||||
VALUES (0, "Phil", "Myman", 30);
|
||||
INSERT INTO person (id, first_name, last_name, age)
|
||||
VALUES (1, "Lem", "Hewitt", 35);
|
@ -0,0 +1,6 @@
|
||||
sleep 0.913123
|
||||
write 3b
|
||||
sleep 0.822303
|
||||
write 73656c656374202a2066726f6d20706572736f6e206f726465722062792061676520646573633b0d
|
||||
sleep 9.068423
|
||||
write 71
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue