summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2017-06-08 14:31:46 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2017-06-08 14:39:41 +0300
commit2c83d0247675ac08791401dc2b341d7f3f201830 (patch)
treeaf415ecb67d1cdef13963718db3ff056ec3fc616
parent4e7f5b5c08095818d7876a86ad6657c57c9a8ad1 (diff)
downloadmailutils-2c83d0247675ac08791401dc2b341d7f3f201830.tar.gz
mailutils-2c83d0247675ac08791401dc2b341d7f3f201830.tar.bz2
Improve locus tracker; provide a testsuite
* include/mailutils/locus.h (mu_locus_track_stat): New struct. (mu_locus_tracker_stat): New proto. (mu_locus_tracker_retreat): Change return type. * libmailutils/locus/debug.c (mu_stream_vlprintf): Don't print spurious \n. (mu_lrange_debug): Fix incorrect call. * libmailutils/locus/tracker.c (mu_locus_track_create): Allocate storage for at least two lines of text. (mu_locus_tracker_stat): New function. (mu_locus_tracker_advance): Handle empty lines (mu_locus_tracker_retreat): Add error handling. * libmailutils/tests/Makefile.am (noinst_PROGRAMS): Add locktrack. * libmailutils/tests/tracker.c: Rename to loctrack.c * libmailutils/tests/testsuite.at: Add new testcase. * libmailutils/tests/loctrack.at: New test case.
-rw-r--r--include/mailutils/locus.h12
-rw-r--r--libmailutils/locus/debug.c6
-rw-r--r--libmailutils/locus/tracker.c68
-rw-r--r--libmailutils/tests/.gitignore2
-rw-r--r--libmailutils/tests/Makefile.am3
-rw-r--r--libmailutils/tests/loctrack.at109
-rw-r--r--libmailutils/tests/loctrack.c (renamed from libmailutils/tests/tracker.c)15
-rw-r--r--libmailutils/tests/testsuite.at1
8 files changed, 192 insertions, 24 deletions
diff --git a/include/mailutils/locus.h b/include/mailutils/locus.h
index 4a454098c..66ba49b2b 100644
--- a/include/mailutils/locus.h
+++ b/include/mailutils/locus.h
@@ -19,6 +19,13 @@ struct mu_locus_range
typedef struct mu_locus_track *mu_locus_track_t;
+struct mu_locus_track_stat
+{
+ unsigned start_line;
+ size_t n_lines;
+ size_t n_chars;
+};
+
int mu_ident_ref (char const *name, char const **refname);
int mu_ident_deref (char const *);
@@ -48,7 +55,10 @@ size_t mu_locus_track_level (mu_locus_track_t trk);
void mu_locus_tracker_advance (struct mu_locus_track *trk,
struct mu_locus_range *loc,
char const *text, size_t leng);
-void mu_locus_tracker_retreat (struct mu_locus_track *trk, size_t n);
+int mu_locus_tracker_retreat (struct mu_locus_track *trk, size_t n);
+int mu_locus_tracker_stat (struct mu_locus_track *trk,
+ struct mu_locus_track_stat *st);
+
void mu_stream_print_locus_range (mu_stream_t stream,
struct mu_locus_range const *loc);
diff --git a/libmailutils/locus/debug.c b/libmailutils/locus/debug.c
index 81e5f3e50..68e85c71f 100644
--- a/libmailutils/locus/debug.c
+++ b/libmailutils/locus/debug.c
@@ -59,8 +59,7 @@ mu_stream_vlprintf (mu_stream_t stream,
{
mu_stream_print_locus_range (stream, loc);
mu_stream_write (stream, ": ", 2, NULL);
- mu_stream_vprintf (mu_strerr, fmt, ap);
- mu_stream_write (stream, "\n", 1, NULL);
+ mu_stream_vprintf (stream, fmt, ap);
}
void
@@ -91,8 +90,9 @@ mu_lrange_debug (struct mu_locus_range const *loc,
}
va_start (ap, fmt);
- mu_stream_lprintf (mu_strerr, loc, fmt, ap);
+ mu_stream_vlprintf (mu_strerr, loc, fmt, ap);
va_end (ap);
+ mu_stream_write (mu_strerr, "\n", 1, NULL);
if (rc == 0)
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
diff --git a/libmailutils/locus/tracker.c b/libmailutils/locus/tracker.c
index c8bc99237..a601a1f30 100644
--- a/libmailutils/locus/tracker.c
+++ b/libmailutils/locus/tracker.c
@@ -2,6 +2,7 @@
#include <errno.h>
#include <mailutils/types.h>
#include <mailutils/locus.h>
+#include <mailutils/error.h>
struct mu_locus_track
{
@@ -38,6 +39,8 @@ mu_locus_track_create (mu_locus_track_t *ret,
return rc;
}
+ if (max_lines < 2)
+ max_lines = 2;
trk->max_lines = max_lines;
trk->head = 0;
trk->level = 0;
@@ -106,14 +109,34 @@ static inline unsigned *
pop (mu_locus_track_t trk)
{
if (trk->level == 0)
- {
- *cols_tos_ptr (trk) = 0;
- return NULL; //FIXME
- }
+ return NULL;
trk->level--;
return cols_tos_ptr (trk);
}
+#ifndef SIZE_MAX
+# define SIZE_MAX (~((size_t)0))
+#endif
+
+int
+mu_locus_tracker_stat (struct mu_locus_track *trk,
+ struct mu_locus_track_stat *st)
+{
+ size_t i, nch = 0;
+
+ for (i = 0; i <= trk->level; i++)
+ {
+ unsigned n = cols_peek (trk, i);
+ if (SIZE_MAX - nch < n)
+ return ERANGE;
+ nch += n;
+ }
+
+ st->start_line = trk->hline;
+ st->n_lines = trk->level;
+ st->n_chars = nch;
+}
+
void
mu_locus_tracker_advance (struct mu_locus_track *trk,
struct mu_locus_range *loc,
@@ -142,27 +165,44 @@ mu_locus_tracker_advance (struct mu_locus_track *trk,
}
else
{
+ /* Text ends with a newline. Keep the previos line number. */
loc->end.mu_line = trk->hline + trk->level - 1;
loc->end.mu_col = cols_peek (trk, trk->level - 1) - 1;
- }
+ if (loc->end.mu_col + 1 == loc->beg.mu_col)
+ {
+ /* This happens if the previous line contained only newline. */
+ loc->beg.mu_col = loc->end.mu_col;
+ }
+ }
}
-void
+int
mu_locus_tracker_retreat (struct mu_locus_track *trk, size_t n)
{
- unsigned *ptr;
+ struct mu_locus_track_stat st;
- ptr = cols_tos_ptr (trk);
- while (n--)
+ mu_locus_tracker_stat (trk, &st);
+ if (n > st.n_chars)
+ return ERANGE;
+ else
{
- if (*ptr == 0)
+ unsigned *ptr = cols_tos_ptr (trk);
+ while (n--)
{
- ptr = pop (trk);
- if (!ptr)
- break;
+ if (*ptr == 0)
+ {
+ ptr = pop (trk);
+ if (!ptr || *ptr == 0)
+ {
+ mu_error ("%s:%d: INTERNAL ERROR: out of pop back\n",
+ __FILE__, __LINE__);
+ return ERANGE;
+ }
+ }
+ --*ptr;
}
- --*ptr;
}
+ return 0;
}
diff --git a/libmailutils/tests/.gitignore b/libmailutils/tests/.gitignore
index 04ceff27e..1b414e3d6 100644
--- a/libmailutils/tests/.gitignore
+++ b/libmailutils/tests/.gitignore
@@ -19,6 +19,7 @@ fsfolder
globtest
imapio
listop
+loctrack
logstr
mailcap
mimehdr
@@ -34,7 +35,6 @@ strout
strtoc
tcli
tempfile
-tracker
url-comp
url-parse
vexp
diff --git a/libmailutils/tests/Makefile.am b/libmailutils/tests/Makefile.am
index e0cccaccf..2b2542c54 100644
--- a/libmailutils/tests/Makefile.am
+++ b/libmailutils/tests/Makefile.am
@@ -54,6 +54,7 @@ noinst_PROGRAMS = \
globtest\
imapio\
listop\
+ loctrack\
logstr\
mailcap\
mimehdr\
@@ -68,7 +69,6 @@ noinst_PROGRAMS = \
strout\
strtoc\
tempfile\
- tracker\
tcli\
url-comp\
url-parse\
@@ -107,6 +107,7 @@ TESTSUITE_AT = \
inline-comment.at\
linecon.at\
list.at\
+ loctrack.at\
logstr.at\
mailcap.at\
mimehdr.at\
diff --git a/libmailutils/tests/loctrack.at b/libmailutils/tests/loctrack.at
new file mode 100644
index 000000000..e96582e54
--- /dev/null
+++ b/libmailutils/tests/loctrack.at
@@ -0,0 +1,109 @@
+# This file is part of GNU Mailutils. -*- Autotest -*-
+# Copyright (C) 2017 Free Software Foundation, Inc.
+#
+# GNU Mailutils is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 3, or (at
+# your option) any later version.
+#
+# GNU Mailutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
+
+AT_BANNER([Locus tracker])
+
+m4_pushdef([TRACKTEST],[
+AT_SETUP([$1])
+AT_KEYWORDS([tracker $2])
+AT_CHECK([loctrack liber $3 <<EOT
+$4[]EOT
+],
+[0],
+[$5],
+[$6])
+AT_CLEANUP
+])
+
+TRACKTEST([normal operation],[],[7],
+[
+agnosco
+veteris\n
+vestigia
+flamme
+\n
+\n
+Publius
+Ovidius
+Naso
+],
+[liber:1.1-7: agnosco
+liber:1.8-14: veteris\n
+liber:2.1-8: vestigia
+liber:2.9-14: flamme
+liber:2.14: \n
+liber:3: \n
+liber:4.1-7: Publius
+liber:4.8-14: Ovidius
+liber:4.15-18: Naso
+])
+
+TRACKTEST([retreat],[],[3],
+[
+agnosco
+\-4
+veteris
+vestigia\n
+flamme
+\-8
+Publius
+],
+[liber:1.1-7: agnosco
+liber:1.4-10: veteris
+liber:1.11-18: vestigia\n
+liber:2.1-6: flamme
+liber:1.18-24: Publius
+])
+
+TRACKTEST([retreat over several lines],[],[4],
+[
+one\n
+two\n
+three
+\-11
+four
+],
+[liber:1.1-3: one\n
+liber:2.1-3: two\n
+liber:3.1-5: three
+liber:1.3-6: four
+])
+
+TRACKTEST([retreat to the beginning],[],[4],
+[one\n
+two\n
+\-8
+three
+],
+[liber:1.1-3: one\n
+liber:2.1-3: two\n
+liber:1.1-5: three
+])
+
+TRACKTEST([too big retreat],[],[2],
+[one\n
+two\n
+\-10
+three
+],
+[liber:1.1-3: one\n
+liber:2.1-3: two\n
+liber:3.1-5: three
+],
+[loctrack: retreat count too big
+])
+
+m4_popdef([TRACKTEST]) \ No newline at end of file
diff --git a/libmailutils/tests/tracker.c b/libmailutils/tests/loctrack.c
index 68a9b6396..354280354 100644
--- a/libmailutils/tests/tracker.c
+++ b/libmailutils/tests/loctrack.c
@@ -33,22 +33,29 @@ main (int argc, char **argv)
char *tok;
n = mu_rtrim_class (buf, MU_CTYPE_SPACE);
- if (buf[0] == '\\')
+ if (n == 0)
+ continue;
+ if (buf[0] == '\\' && buf[1] == '-')
{
- long x = strtol (buf+1, &end, 10);
+ long x = strtol (buf+2, &end, 10);
if (*end || x == 0)
{
mu_error ("bad number");
continue;
}
- mu_locus_tracker_retreat (trk, x);
+ rc = mu_locus_tracker_retreat (trk, x);
+ if (rc == ERANGE)
+ mu_error ("retreat count too big");
+ else if (rc)
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_locus_tracker_retreat", buf+2,
+ rc);
}
else
{
mu_c_str_unescape (buf, "\\\n", "\\n", &tok);
mu_locus_tracker_advance (trk, &lr, tok, strlen (tok));
free (tok);
- mu_lrange_debug (&lr, "%s", buf);
+ mu_stream_lprintf (mu_strout, &lr, "%s\n", buf);
}
}
return 0;
diff --git a/libmailutils/tests/testsuite.at b/libmailutils/tests/testsuite.at
index 1dc1eb37c..9518cd749 100644
--- a/libmailutils/tests/testsuite.at
+++ b/libmailutils/tests/testsuite.at
@@ -212,3 +212,4 @@ m4_include([msgset.at])
m4_include([globtest.at])
+m4_include([loctrack.at])

Return to:

Send suggestions and report system problems to the System administrator.