From: Bo Yang <struggleyb.nku@gmail.com>
To: git@vger.kernel.org
Cc: Jens.Lehmann@web.de, trast@student.ethz.ch, gitster@pobox.com
Subject: [PATCH V5 04/17] Refactor parse_loc
Date: Wed, 11 Aug 2010 23:03:29 +0800 [thread overview]
Message-ID: <1281539022-31616-5-git-send-email-struggleyb.nku@gmail.com> (raw)
In-Reply-To: <1281539022-31616-1-git-send-email-struggleyb.nku@gmail.com>
Both 'git blame -L' and 'git log -L' parse the same style
of line number arguments, so put the 'parse_loc' function
to line.c and export it.
The caller of parse_loc should provide a callback function
which is used to calculate the start position of the nth line.
Other parts such as regexp search, line number parsing are
abstracted and re-used.
Note that, we can use '$' to specify the last line of a file.
Signed-off-by: Bo Yang <struggleyb.nku@gmail.com>
---
builtin/blame.c | 89 +++++-------------------------------------------------
line.c | 52 ++++++++++++++++++++------------
line.h | 5 +++
3 files changed, 46 insertions(+), 100 deletions(-)
diff --git a/builtin/blame.c b/builtin/blame.c
index 01e62fd..17b71cd 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -21,6 +21,7 @@
#include "parse-options.h"
#include "utf8.h"
#include "userdiff.h"
+#include "line.h"
static char blame_usage[] = "git blame [options] [rev-opts] [rev] [--] file";
@@ -541,11 +542,16 @@ static void dup_entry(struct blame_entry *dst, struct blame_entry *src)
dst->score = 0;
}
-static const char *nth_line(struct scoreboard *sb, int lno)
+static const char *nth_line(struct scoreboard *sb, long lno)
{
return sb->final_buf + sb->lineno[lno];
}
+static const char *nth_line_cb(void *data, long lno)
+{
+ return nth_line((struct scoreboard *)data, lno);
+}
+
/*
* It is known that lines between tlno to same came from parent, and e
* has an overlap with that range. it also is known that parent's
@@ -1907,83 +1913,6 @@ static const char *add_prefix(const char *prefix, const char *path)
}
/*
- * Parsing of (comma separated) one item in the -L option
- */
-static const char *parse_loc(const char *spec,
- struct scoreboard *sb, long lno,
- long begin, long *ret)
-{
- char *term;
- const char *line;
- long num;
- int reg_error;
- regex_t regexp;
- regmatch_t match[1];
-
- /* Allow "-L <something>,+20" to mean starting at <something>
- * for 20 lines, or "-L <something>,-5" for 5 lines ending at
- * <something>.
- */
- if (1 < begin && (spec[0] == '+' || spec[0] == '-')) {
- num = strtol(spec + 1, &term, 10);
- if (term != spec + 1) {
- if (spec[0] == '-')
- num = 0 - num;
- if (0 < num)
- *ret = begin + num - 2;
- else if (!num)
- *ret = begin;
- else
- *ret = begin + num;
- return term;
- }
- return spec;
- }
- num = strtol(spec, &term, 10);
- if (term != spec) {
- *ret = num;
- return term;
- }
- if (spec[0] != '/')
- return spec;
-
- /* it could be a regexp of form /.../ */
- for (term = (char *) spec + 1; *term && *term != '/'; term++) {
- if (*term == '\\')
- term++;
- }
- if (*term != '/')
- return spec;
-
- /* try [spec+1 .. term-1] as regexp */
- *term = 0;
- begin--; /* input is in human terms */
- line = nth_line(sb, begin);
-
- if (!(reg_error = regcomp(®exp, spec + 1, REG_NEWLINE)) &&
- !(reg_error = regexec(®exp, line, 1, match, 0))) {
- const char *cp = line + match[0].rm_so;
- const char *nline;
-
- while (begin++ < lno) {
- nline = nth_line(sb, begin);
- if (line <= cp && cp < nline)
- break;
- line = nline;
- }
- *ret = begin;
- regfree(®exp);
- *term++ = '/';
- return term;
- }
- else {
- char errbuf[1024];
- regerror(reg_error, ®exp, errbuf, 1024);
- die("-L parameter '%s': %s", spec + 1, errbuf);
- }
-}
-
-/*
* Parsing of -L option
*/
static void prepare_blame_range(struct scoreboard *sb,
@@ -1993,9 +1922,9 @@ static void prepare_blame_range(struct scoreboard *sb,
{
const char *term;
- term = parse_loc(bottomtop, sb, lno, 1, bottom);
+ term = parse_loc(bottomtop, nth_line_cb, sb, lno, 1, bottom);
if (*term == ',') {
- term = parse_loc(term + 1, sb, lno, *bottom + 1, top);
+ term = parse_loc(term + 1, nth_line_cb, sb, lno, *bottom + 1, top);
if (*term)
usage(blame_usage);
}
diff --git a/line.c b/line.c
index e277fa6..6c5f69e 100644
--- a/line.c
+++ b/line.c
@@ -95,25 +95,29 @@ static void fill_line_ends(struct diff_filespec *spec, long *lines,
*line_ends = ends;
}
-static const char *nth_line(struct diff_filespec *spec, long line,
- long lines, unsigned long *line_ends)
+struct nth_line_cb {
+ struct diff_filespec *spec;
+ long lines;
+ unsigned long *line_ends;
+};
+
+static const char *nth_line(void *data, long line)
{
- assert(line < lines);
- assert(spec && spec->data);
+ struct nth_line_cb *d = data;
+ assert(d && line < d->lines);
+ assert(d->spec && d->spec->data);
if (line == 0)
- return (char *)spec->data;
+ return (char *)d->spec->data;
else
- return (char *)spec->data + line_ends[line] + 1;
+ return (char *)d->spec->data + d->line_ends[line] + 1;
}
/*
- * copied from blame.c, indeed, we can even to use this to test
- * whether line log works. :)
+ * Parsing of (comma separated) one item in the -L option
*/
-static const char *parse_loc(const char *spec, struct diff_filespec *file,
- long lines, unsigned long *line_ends,
- long begin, long *ret)
+const char *parse_loc(const char *spec, nth_line_fn_t nth_line,
+ void *data, long lines, long begin, long *ret)
{
char *term;
const char *line;
@@ -122,6 +126,13 @@ static const char *parse_loc(const char *spec, struct diff_filespec *file,
regex_t regexp;
regmatch_t match[1];
+ /* Catch the '$' matcher, now it is used to match the last
+ * line of the file. */
+ if (spec[0] == '$') {
+ *ret = lines;
+ return spec + 1;
+ }
+
/* Allow "-L <something>,+20" to mean starting at <something>
* for 20 lines, or "-L <something>,-5" for 5 lines ending at
* <something>.
@@ -160,7 +171,7 @@ static const char *parse_loc(const char *spec, struct diff_filespec *file,
/* try [spec+1 .. term-1] as regexp */
*term = 0;
begin--; /* input is in human terms */
- line = nth_line(file, begin, lines, line_ends);
+ line = nth_line(data, begin);
if (!(reg_error = regcomp(®exp, spec + 1, REG_NEWLINE)) &&
!(reg_error = regexec(®exp, line, 1, match, 0))) {
@@ -168,7 +179,7 @@ static const char *parse_loc(const char *spec, struct diff_filespec *file,
const char *nline;
while (begin++ < lines) {
- nline = nth_line(file, begin, lines, line_ends);
+ nline = nth_line(data, begin);
if (line <= cp && cp < nline)
break;
line = nline;
@@ -188,10 +199,11 @@ static void parse_range(long lines, unsigned long *line_ends,
struct line_range *r, struct diff_filespec *spec)
{
const char *term;
+ struct nth_line_cb data = {spec, lines, line_ends};
- term = parse_loc(r->arg, spec, lines, line_ends, 1, &r->start);
+ term = parse_loc(r->arg, nth_line, &data, lines - 1, 1, &r->start);
if (*term == ',') {
- term = parse_loc(term + 1, spec, lines, line_ends,
+ term = parse_loc(term + 1, nth_line, &data, lines - 1,
r->start + 1, &r->end);
if (*term)
die("-L parameter's argument should be <start>,<end>");
@@ -200,16 +212,16 @@ static void parse_range(long lines, unsigned long *line_ends,
if (*term)
die("-L parameter's argument should be <start>,<end>");
+ if (r->start < 1)
+ r->start = 1;
+ if (r->end >= lines)
+ r->end = lines - 1;
+
if (r->start > r->end) {
long tmp = r->start;
r->start = r->end;
r->end = tmp;
}
-
- if (r->start < 1)
- r->start = 1;
- if (r->end >= lines)
- r->end = lines - 1;
}
static void parse_lines(struct commit *commit, struct diff_line_range *r)
diff --git a/line.h b/line.h
index a04af86..5bde828 100644
--- a/line.h
+++ b/line.h
@@ -8,6 +8,8 @@ struct commit;
struct diff_line_range;
struct diff_options;
+typedef const char *(*nth_line_fn_t)(void *data, long lno);
+
struct print_range {
int start, end; /* Line range of post-image */
int pstart, pend; /* Line range of pre-image */
@@ -125,4 +127,7 @@ extern void add_line_range(struct rev_info *revs, struct commit *commit,
extern struct diff_line_range *lookup_line_range(struct rev_info *revs,
struct commit *commit);
+const char *parse_loc(const char *spec, nth_line_fn_t nth_line,
+ void *data, long lines, long begin, long *ret);
+
#endif
--
1.7.2.19.g79e5d
next prev parent reply other threads:[~2010-08-11 15:04 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-08-11 15:03 [PATCH V5 00/17] Reroll a version 5 of this series Bo Yang
2010-08-11 15:03 ` [PATCH V5 01/17] parse-options: enhance STOP_AT_NON_OPTION Bo Yang
2010-08-11 15:03 ` [PATCH V5 02/17] parse-options: add two helper functions Bo Yang
2010-08-11 15:03 ` [PATCH V5 03/17] Add the basic data structure for line level history Bo Yang
2010-08-11 15:03 ` Bo Yang [this message]
2010-08-11 15:03 ` [PATCH V5 05/17] Parse the -L options Bo Yang
2010-08-11 15:03 ` [PATCH V5 06/17] Export three functions from diff.c Bo Yang
2010-08-11 15:03 ` [PATCH V5 07/17] Add range clone functions Bo Yang
2010-08-11 15:03 ` [PATCH V5 08/17] map/take range to the parent of commits Bo Yang
2010-08-11 15:03 ` [PATCH V5 09/17] Print the line log Bo Yang
2010-08-11 15:03 ` [PATCH V5 10/17] Hook line history into cmd_log, ensuring a topo-ordered walk Bo Yang
2010-08-11 15:03 ` [PATCH V5 11/17] Make rewrite_parents public to other part of git Bo Yang
2010-08-11 15:03 ` [PATCH V5 12/17] Make graph_next_line external " Bo Yang
2010-08-11 15:03 ` [PATCH V5 13/17] Add parent rewriting to line history browser Bo Yang
2010-08-30 17:10 ` log -L crash (Re: [PATCH V5 13/17] Add parent rewriting to line history browser) Jonathan Nieder
2010-09-01 14:47 ` Bo Yang
2010-09-11 21:10 ` [PATCH] log -L: do not free parents lists we might need again Thomas Rast
2010-08-11 15:03 ` [PATCH V5 14/17] Add --graph prefix before line history output Bo Yang
2010-08-11 15:03 ` [PATCH V5 15/17] Add --full-line-diff option Bo Yang
2010-08-11 15:03 ` [PATCH V5 16/17] Add tests for line history browser Bo Yang
2010-08-12 1:25 ` Ævar Arnfjörð Bjarmason
2010-08-12 12:24 ` Bo Yang
2010-08-12 16:27 ` Ævar Arnfjörð Bjarmason
2010-08-12 20:37 ` Junio C Hamano
2010-08-12 21:06 ` Junio C Hamano
2010-08-11 15:03 ` [PATCH V5 17/17] Document " Bo Yang
2010-08-12 8:31 ` [PATCH V5 00/17] Reroll a version 5 of this series david
2010-08-12 17:23 ` Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1281539022-31616-5-git-send-email-struggleyb.nku@gmail.com \
--to=struggleyb.nku@gmail.com \
--cc=Jens.Lehmann@web.de \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=trast@student.ethz.ch \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).