summaryrefslogtreecommitdiffabout
Side-by-side diff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--NEWS9
-rw-r--r--am/bison.m411
-rw-r--r--am/flex.m412
-rw-r--r--comsat/action.c31
-rw-r--r--configure.ac8
-rw-r--r--include/mailutils/Makefile.am4
-rw-r--r--include/mailutils/assoc.h2
-rw-r--r--include/mailutils/auth.h3
-rw-r--r--include/mailutils/cfg.h7
-rw-r--r--include/mailutils/debug.h2
-rw-r--r--include/mailutils/diag.h7
-rw-r--r--include/mailutils/locus.h111
-rw-r--r--include/mailutils/log.h4
-rw-r--r--include/mailutils/mailutils.h1
-rw-r--r--include/mailutils/sieve.h14
-rw-r--r--include/mailutils/stream.h27
-rw-r--r--include/mailutils/sys/logstream.h3
-rw-r--r--include/mailutils/types.hin16
-rw-r--r--include/mailutils/yyloc.h46
-rw-r--r--libmailutils/Makefile.am3
-rw-r--r--libmailutils/base/.gitignore1
-rw-r--r--libmailutils/base/Makefile.am17
-rw-r--r--libmailutils/base/assoc.c15
-rw-r--r--libmailutils/base/copyfile.c4
-rw-r--r--libmailutils/base/gylwrap.conf3
-rw-r--r--libmailutils/base/wicket.c4
-rw-r--r--libmailutils/cfg/.gitignore1
-rw-r--r--libmailutils/cfg/Makefile.am22
-rw-r--r--libmailutils/cfg/format.c6
-rw-r--r--libmailutils/cfg/gylwrap.conf4
-rw-r--r--libmailutils/cfg/lexer.l69
-rw-r--r--libmailutils/cfg/parser.y141
-rw-r--r--libmailutils/diag/diag.c50
-rw-r--r--libmailutils/locus/Makefile.am31
-rw-r--r--libmailutils/locus/debug.c74
-rw-r--r--libmailutils/locus/filprloc.c7
-rw-r--r--libmailutils/locus/genprloc.c71
-rw-r--r--libmailutils/locus/ident.c152
-rw-r--r--libmailutils/locus/linetrack.c268
-rw-r--r--libmailutils/locus/locus.c101
-rw-r--r--libmailutils/locus/strprloc.c10
-rw-r--r--libmailutils/stream/logstream.c313
-rw-r--r--libmailutils/tests/.gitignore2
-rw-r--r--libmailutils/tests/Makefile.am4
-rw-r--r--libmailutils/tests/linetrack.at109
-rw-r--r--libmailutils/tests/linetrack.c66
-rw-r--r--libmailutils/tests/logstr.at77
-rw-r--r--libmailutils/tests/logstr.c729
-rw-r--r--libmailutils/tests/testsuite.at6
-rw-r--r--libmailutils/tests/wicket.c2
-rw-r--r--libmailutils/tests/xscript.at1
-rw-r--r--libmu_auth/radius.c38
-rw-r--r--libmu_sieve/Makefile.am23
-rw-r--r--libmu_sieve/actions.c4
-rw-r--r--libmu_sieve/comparator.c22
-rw-r--r--libmu_sieve/extensions/moderator.c10
-rw-r--r--libmu_sieve/gylwrap.conf4
-rw-r--r--libmu_sieve/mem.c27
-rw-r--r--libmu_sieve/prog.c69
-rw-r--r--libmu_sieve/require.c2
-rw-r--r--libmu_sieve/runtime.c53
-rw-r--r--libmu_sieve/sieve-gram.y (renamed from libmu_sieve/sieve.y)153
-rw-r--r--libmu_sieve/sieve-lex.l (renamed from libmu_sieve/sieve.l)89
-rw-r--r--libmu_sieve/sieve-priv.h19
-rw-r--r--libmu_sieve/util.c45
-rw-r--r--libmu_sieve/variables.c9
-rw-r--r--mail/Makefile.am1
-rw-r--r--mail/source.c12
-rw-r--r--mh/.gitignore3
-rw-r--r--mh/Makefile.am51
-rw-r--r--mh/gylwrap.conf13
-rw-r--r--mh/mh.h1
-rw-r--r--mh/mh_alias_gram.y (renamed from mh/mh_alias.y)46
-rw-r--r--mh/mh_alias_lex.l (renamed from mh/mh_alias.l)254
-rw-r--r--mh/pick-gram.y (renamed from mh/pick.y)0
-rw-r--r--mh/tests/ali.at4
-rw-r--r--mimeview/.gitignore11
-rw-r--r--mimeview/Makefile.am27
-rw-r--r--mimeview/grammar.y (renamed from mimeview/mimetypes.y)32
-rw-r--r--mimeview/gylwrap.conf3
-rw-r--r--mimeview/lexer.l (renamed from mimeview/mimetypes.l)164
-rw-r--r--mimeview/mimeview.c14
-rw-r--r--mimeview/mimeview.h28
-rw-r--r--mimeview/tests/testsuite.at89
-rwxr-xr-xmu-aux/gencl20
-rwxr-xr-xmu-aux/gitinfo3
-rwxr-xr-xmu-aux/gylwrap533
-rw-r--r--mu/libexec/dbm.c31
-rw-r--r--mu/libexec/logger.c73
-rw-r--r--mu/libexec/wicket.c2
-rw-r--r--po/POTFILES.in8
-rw-r--r--sieve/sieve.c9
-rw-r--r--sieve/tests/i-numeric.at2
93 files changed, 3448 insertions, 1234 deletions
diff --git a/NEWS b/NEWS
index 266a999..e351691 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-GNU mailutils NEWS -- history of user-visible changes. 2017-06-01
+GNU mailutils NEWS -- history of user-visible changes. 2017-06-16
Copyright (C) 2002-2017 Free Software Foundation, Inc.
See the end of file for copying conditions.
@@ -75,6 +75,13 @@ value is anything but "no", the settings from the global "tls" section
will be used. In this case, it is an error if the global "tls"
section is not defined.
+* Source location API
+
+Libmailutils provides functions for keeping track of locations in
+source files for diagnostic purposes.
+
+* Improve error reporting
+
* AM_GNU_MAILUTILS autoconf macro
Required version must be literal string.
diff --git a/am/bison.m4 b/am/bison.m4
new file mode 100644
index 0000000..875b326
--- a/dev/null
+++ b/am/bison.m4
@@ -0,0 +1,11 @@
+# bison.m4 serial 1
+AC_DEFUN([MU_PROG_BISON],
+[
+ if test "x$ac_cv_prog_YACC" = x; then
+ AC_PROG_YACC
+ if ! $YACC --version 2>/dev/null | grep -q '^bison '; then
+ YACC="$SHELL $missing_dir/missing bison"
+ fi
+ fi
+])
+
diff --git a/am/flex.m4 b/am/flex.m4
new file mode 100644
index 0000000..58d2c4b
--- a/dev/null
+++ b/am/flex.m4
@@ -0,0 +1,12 @@
+# flex.m4 serial 1
+AC_DEFUN([MU_PROG_FLEX],
+[
+ if test "x$LEX" = x; then
+ AC_PROG_LEX
+ if ! $LEX --version 2>/dev/null | grep -q '^flex '; then
+ LEX="$SHELL $missing_dir/missing flex"
+ AC_SUBST([LEX_OUTPUT_ROOT], [lex.yy])
+ AC_SUBST([LEXLIB], [''])
+ fi
+])
+
diff --git a/comsat/action.c b/comsat/action.c
index 6ff766a..24080a5 100644
--- a/comsat/action.c
+++ b/comsat/action.c
@@ -298,7 +298,7 @@ struct biffrc_environ
mu_stream_t logstr;
mu_message_t msg;
mu_stream_t input;
- struct mu_locus locus;
+ struct mu_locus_range locus;
int use_default;
char *errbuf;
size_t errsize;
@@ -523,16 +523,16 @@ eval_biffrc (struct biffrc_environ *env)
ws.ws_comment = "#";
wsflags = MU_WRDSF_DEFFLAGS | MU_WRDSF_COMMENT;
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
- MU_IOCTL_LOGSTREAM_SET_LOCUS, &env->locus);
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &env->locus);
mu_stream_ioctl (env->logstr, MU_IOCTL_LOGSTREAM,
- MU_IOCTL_LOGSTREAM_SET_LOCUS, &env->locus);
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &env->locus);
while (mu_stream_getline (env->input, &stmt, &size, &n) == 0 && n > 0)
{
if (strncmp (stmt, "#line ", 6) == 0)
{
char *p;
- env->locus.mu_line = strtoul (stmt + 6, &p, 10);
+ env->locus.beg.mu_line = strtoul (stmt + 6, &p, 10);
if (*p != '\n')
{
report_error (env, _("malformed #line directive: %s"));
@@ -541,10 +541,10 @@ eval_biffrc (struct biffrc_environ *env)
{
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_SET_LOCUS_LINE,
- &env->locus.mu_line);
+ &env->locus.beg.mu_line);
mu_stream_ioctl (env->logstr, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_SET_LOCUS_LINE,
- &env->locus.mu_line);
+ &env->locus.beg.mu_line);
}
continue;
}
@@ -600,9 +600,9 @@ eval_biffrc (struct biffrc_environ *env)
free (stmt);
mu_wordsplit_free (&ws);
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
- MU_IOCTL_LOGSTREAM_SET_LOCUS, NULL);
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, NULL);
mu_stream_ioctl (env->logstr, MU_IOCTL_LOGSTREAM,
- MU_IOCTL_LOGSTREAM_SET_LOCUS, NULL);
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, NULL);
}
void
@@ -645,13 +645,14 @@ run_user_action (const char *device, mu_message_t msg)
if (!rcname)
{
mu_diag_funcall (MU_DIAG_ERROR, "mu_make_file_name", NULL, ENOMEM);
- env.locus.mu_file = BIFF_RC;
+ env.locus.beg.mu_file = BIFF_RC;
}
else
- env.locus.mu_file = rcname;
+ env.locus.beg.mu_file = rcname;
- env.locus.mu_line = 1;
- env.locus.mu_col = 0;
+ env.locus.beg.mu_line = 1;
+ env.locus.beg.mu_col = 0;
+ memset (&env.locus.end, 0, sizeof env.locus.end);
env.use_default = 0;
eval_biffrc (&env);
mu_stream_destroy (&env.input);
@@ -679,9 +680,9 @@ run_user_action (const char *device, mu_message_t msg)
}
else
{
- env.locus.mu_file = "<default>";
- env.locus.mu_line = 1;
- env.locus.mu_col = 0;
+ env.locus.beg.mu_file = "<default>";
+ env.locus.beg.mu_line = 1;
+ env.locus.beg.mu_col = 0;
eval_biffrc (&env);
mu_stream_destroy (&env.input);
}
diff --git a/configure.ac b/configure.ac
index 3f84188..86bc16f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -71,6 +71,9 @@ AC_SUBST(MU_LIB_COMMON_INCLUDES,'-I${top_builddir} -I${top_srcdir}/include -I${
AC_SUBST(MU_APP_COMMON_INCLUDES,'-I${srcdir} -I${top_srcdir}/include -I${top_srcdir}/lib -I${top_srcdir}/lib/gnu -I${top_builddir}/lib/gnu -I${top_builddir} -I${top_builddir}/include')
+# Use our replacement for the ylwrap tool
+AC_SUBST([MU_YLWRAP],'$(mu_aux_dir)/gylwrap --')
+
dnl Check for programs
AC_PROG_CC
AM_PROG_CC_C_O
@@ -80,8 +83,8 @@ AC_PROG_INSTALL
AC_PROG_LN_S
AC_LIBTOOL_DLOPEN
AC_PROG_LIBTOOL
-AC_PROG_YACC
-AM_PROG_LEX
+MU_PROG_BISON
+MU_PROG_LEX
AM_PROG_LIBTOOL
## Predefine several variables used to display configuration status
@@ -1495,6 +1498,7 @@ AC_CONFIG_FILES([
libmailutils/filter/Makefile
libmailutils/imapio/Makefile
libmailutils/list/Makefile
+ libmailutils/locus/Makefile
libmailutils/mailbox/Makefile
libmailutils/mailer/Makefile
libmailutils/mime/Makefile
diff --git a/include/mailutils/Makefile.am b/include/mailutils/Makefile.am
index 6b83274..95de7e7 100644
--- a/include/mailutils/Makefile.am
+++ b/include/mailutils/Makefile.am
@@ -73,6 +73,7 @@ pkginclude_HEADERS = \
kwd.h\
ldap.h\
list.h\
+ locus.h\
locker.h\
log.h\
mailbox.h\
@@ -116,7 +117,8 @@ pkginclude_HEADERS = \
types.h\
url.h\
version.h\
- wordsplit.h
+ wordsplit.h\
+ yyloc.h
if MU_COND_SUPPORT_CXX
CPP_DIR = cpp
diff --git a/include/mailutils/assoc.h b/include/mailutils/assoc.h
index a8f9845..930ff2d 100644
--- a/include/mailutils/assoc.h
+++ b/include/mailutils/assoc.h
@@ -37,6 +37,8 @@ int mu_assoc_install (mu_assoc_t assoc, const char *name, void *value);
int mu_assoc_lookup_ref (mu_assoc_t assoc, const char *name, void *dataptr);
int mu_assoc_install_ref (mu_assoc_t assoc, const char *name, void *pval);
+int mu_assoc_install_ref2 (mu_assoc_t assoc, const char *name,
+ void *ret_val, const char **ret_name);
int mu_assoc_get_iterator (mu_assoc_t assoc, mu_iterator_t *piterator);
int mu_assoc_remove (mu_assoc_t assoc, const char *name);
diff --git a/include/mailutils/auth.h b/include/mailutils/auth.h
index 04dbfd3..998779b 100644
--- a/include/mailutils/auth.h
+++ b/include/mailutils/auth.h
@@ -20,6 +20,7 @@
#define _MAILUTILS_AUTH_H
#include <mailutils/types.h>
+#include <mailutils/locus.h>
#ifdef __cplusplus
extern "C" {
@@ -77,7 +78,7 @@ int mu_wicket_set_get_ticket (mu_wicket_t wicket,
int mu_file_wicket_create (mu_wicket_t *pwicket, const char *filename);
struct mu_debug_locus;
-int mu_wicket_stream_match_url (mu_stream_t stream, struct mu_locus *loc,
+int mu_wicket_stream_match_url (mu_stream_t stream, struct mu_locus_point *loc,
mu_url_t url, int parse_flags,
mu_url_t *pticket_url);
int mu_wicket_file_match_url (const char *name, mu_url_t url,
diff --git a/include/mailutils/cfg.h b/include/mailutils/cfg.h
index 8ccd7f4..de84af6 100644
--- a/include/mailutils/cfg.h
+++ b/include/mailutils/cfg.h
@@ -23,6 +23,7 @@
#include <mailutils/debug.h>
#include <mailutils/opool.h>
#include <mailutils/util.h>
+#include <mailutils/locus.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@@ -64,7 +65,7 @@ enum mu_cfg_node_type
struct mu_cfg_node
{
- struct mu_locus locus;
+ struct mu_locus_range locus;
enum mu_cfg_node_type type;
char *tag;
mu_config_value_t *label;
@@ -119,8 +120,6 @@ int mu_cfg_tree_union (mu_cfg_tree_t **pa, mu_cfg_tree_t **pb);
int mu_cfg_tree_postprocess (mu_cfg_tree_t *tree,
struct mu_cfg_parse_hints *hints);
-extern struct mu_locus mu_cfg_locus;
-
mu_opool_t mu_cfg_lexer_pool (void);
#define MU_CFG_ITER_OK 0
@@ -285,7 +284,7 @@ int mu_cfg_parse_file (mu_cfg_tree_t **return_tree, const char *file,
int mu_cfg_tree_create (struct mu_cfg_tree **ptree);
mu_cfg_node_t *mu_cfg_tree_create_node (struct mu_cfg_tree *tree,
enum mu_cfg_node_type type,
- const struct mu_locus *loc,
+ const struct mu_locus_range *loc,
const char *tag,
const char *label,
mu_list_t nodelist);
diff --git a/include/mailutils/debug.h b/include/mailutils/debug.h
index 647a058..8ec2e88 100644
--- a/include/mailutils/debug.h
+++ b/include/mailutils/debug.h
@@ -106,7 +106,7 @@ int mu_debug_get_iterator (mu_iterator_t *piterator, int skipunset);
if (mu_debug_line_info) \
{ \
mu_debug_log_begin ("\033X<%d>%s:%d: ", \
- MU_LOGMODE_LOCUS, __FILE__, __LINE__); \
+ MU_LOGMODE_LOCUS, __FILE__, __LINE__); \
mu_debug_log_end s; \
} \
else \
diff --git a/include/mailutils/diag.h b/include/mailutils/diag.h
index 3b57aae..03a0eac 100644
--- a/include/mailutils/diag.h
+++ b/include/mailutils/diag.h
@@ -24,6 +24,7 @@
#include <mailutils/types.h>
#include <mailutils/log.h>
#include <mailutils/debug.h>
+#include <mailutils/locus.h>
#ifdef __cplusplus
extern "C" {
@@ -51,8 +52,10 @@ void mu_diag_cont_printf (const char *fmt, ...) MU_PRINTFLIKE(1,2);
void mu_diag_voutput (int, const char *, va_list);
void mu_diag_output (int, const char *, ...) MU_PRINTFLIKE(2,3);
-void mu_diag_at_locus (int level, struct mu_locus const *loc,
- const char *fmt, ...);
+void mu_diag_at_locus_point (int level, struct mu_locus_point const *loc,
+ const char *fmt, ...);
+void mu_diag_at_locus_range (int level, struct mu_locus_range const *loc,
+ const char *fmt, ...);
int mu_diag_level_to_syslog (int level);
const char *mu_diag_level_to_string (int level);
diff --git a/include/mailutils/locus.h b/include/mailutils/locus.h
new file mode 100644
index 0000000..f8efa13
--- a/dev/null
+++ b/include/mailutils/locus.h
@@ -0,0 +1,111 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2017 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _MAILUTILS_LOCUS_H
+#define _MAILUTILS_LOCUS_H
+
+#include <string.h>
+#include <stdarg.h>
+
+struct mu_locus_point
+{
+ char const *mu_file;
+ unsigned mu_line;
+ unsigned mu_col;
+};
+
+#define MU_LOCUS_POINT_INITIALIZER { NULL, 0, 0 }
+
+struct mu_locus_range
+{
+ struct mu_locus_point beg;
+ struct mu_locus_point end;
+};
+
+#define MU_LOCUS_RANGE_INITIALIZER \
+ { MU_LOCUS_POINT_INITIALIZER, MU_LOCUS_POINT_INITIALIZER }
+
+typedef struct mu_linetrack *mu_linetrack_t;
+
+struct mu_linetrack_stat
+{
+ unsigned start_line; /* Start line number (1-based) */
+ size_t n_lines; /* Number of lines, including the recent (incomplete)
+ one */
+ size_t n_chars; /* Total number of characters */
+};
+
+int mu_ident_ref (char const *name, char const **refname);
+int mu_ident_deref (char const *);
+void mu_ident_stat (mu_stream_t str);
+
+int mu_locus_point_set_file (struct mu_locus_point *pt, const char *filename);
+void mu_locus_point_init (struct mu_locus_point *pt);
+void mu_locus_point_deinit (struct mu_locus_point *pt);
+int mu_locus_point_copy (struct mu_locus_point *dest,
+ struct mu_locus_point const *src);
+
+void mu_locus_range_init (struct mu_locus_range *dest);
+int mu_locus_range_copy (struct mu_locus_range *dest,
+ struct mu_locus_range const *src);
+void mu_locus_range_deinit (struct mu_locus_range *lr);
+
+static inline int
+mu_locus_point_same_file (struct mu_locus_point const *a,
+ struct mu_locus_point const *b)
+{
+ return a->mu_file == b->mu_file
+ || (a->mu_file && b->mu_file && strcmp(a->mu_file, b->mu_file) == 0);
+}
+
+static inline int
+mu_locus_point_same_line (struct mu_locus_point const *a,
+ struct mu_locus_point const *b)
+{
+ return mu_locus_point_same_file (a, b) && a->mu_line == b->mu_line;
+}
+
+int mu_linetrack_create (mu_linetrack_t *ret,
+ char const *file_name, size_t max_lines);
+int mu_linetrack_rebase (mu_linetrack_t trk, struct mu_locus_point const *pt);
+void mu_linetrack_free (mu_linetrack_t trk);
+void mu_linetrack_destroy (mu_linetrack_t *trk);
+void mu_linetrack_advance (mu_linetrack_t trk,
+ struct mu_locus_range *loc,
+ char const *text, size_t leng);
+int mu_linetrack_retreat (mu_linetrack_t trk, size_t n);
+
+int mu_linetrack_locus (struct mu_linetrack *trk, struct mu_locus_point *lp);
+int mu_linetrack_stat (mu_linetrack_t trk, struct mu_linetrack_stat *st);
+int mu_linetrack_at_bol (struct mu_linetrack *trk);
+
+void mu_stream_print_locus_point (mu_stream_t stream,
+ struct mu_locus_point const *lpt);
+void mu_stream_print_locus_range (mu_stream_t stream,
+ struct mu_locus_range const *loc);
+
+void mu_stream_vlprintf (mu_stream_t stream,
+ struct mu_locus_range const *loc,
+ char const *fmt, va_list ap);
+void mu_stream_lprintf (mu_stream_t stream,
+ struct mu_locus_range const *loc,
+ char const *fmt, ...);
+void mu_lrange_debug (struct mu_locus_range const *loc,
+ char const *fmt, ...);
+
+
+#endif
diff --git a/include/mailutils/log.h b/include/mailutils/log.h
index 53cccd2..34aeb63 100644
--- a/include/mailutils/log.h
+++ b/include/mailutils/log.h
@@ -32,8 +32,8 @@ extern "C" {
#define MU_LOG_ALERT 6
#define MU_LOG_EMERG 7
-#define MU_LOGMODE_SEVERITY 0x0001
-#define MU_LOGMODE_LOCUS 0x0002
+#define MU_LOGMODE_SEVERITY 0x0001
+#define MU_LOGMODE_LOCUS 0x0002
int mu_log_stream_create (mu_stream_t *, mu_stream_t);
int mu_syslog_stream_create (mu_stream_t *, int);
diff --git a/include/mailutils/mailutils.h b/include/mailutils/mailutils.h
index be4985e..d5aadf8 100644
--- a/include/mailutils/mailutils.h
+++ b/include/mailutils/mailutils.h
@@ -36,6 +36,7 @@
#include <mailutils/header.h>
#include <mailutils/iterator.h>
#include <mailutils/kwd.h>
+#include <mailutils/locus.h>
#include <mailutils/sieve.h>
#include <mailutils/list.h>
#include <mailutils/locker.h>
diff --git a/include/mailutils/sieve.h b/include/mailutils/sieve.h
index 8d9c2c1..63d81c7 100644
--- a/include/mailutils/sieve.h
+++ b/include/mailutils/sieve.h
@@ -23,6 +23,7 @@
#include <stdarg.h>
#include <mailutils/mailutils.h>
#include <mailutils/cli.h>
+#include <mailutils/locus.h>
#ifdef __cplusplus
extern "C" {
@@ -87,6 +88,7 @@ typedef struct
{
mu_sieve_data_type type;
char *tag;
+ struct mu_locus_range locus;
union mu_sieve_value_storage v;
} mu_sieve_value_t;
@@ -162,7 +164,9 @@ void mu_sieve_reclaim_default (void *p);
void mu_sieve_reclaim_value (void *p);
size_t mu_sieve_value_create (mu_sieve_machine_t mach,
- mu_sieve_data_type type, void *data);
+ mu_sieve_data_type type,
+ struct mu_locus_range const *locus,
+ void *data);
/* Symbol space functions */
mu_sieve_registry_t *mu_sieve_registry_add (mu_sieve_machine_t mach,
@@ -287,7 +291,7 @@ int mu_sieve_set_dry_run (mu_sieve_machine_t mach, int val);
void mu_sieve_get_argc (mu_sieve_machine_t mach, size_t *args, size_t *tags);
mu_mailer_t mu_sieve_get_mailer (mu_sieve_machine_t mach);
-int mu_sieve_get_locus (mu_sieve_machine_t mach, struct mu_locus *);
+int mu_sieve_get_locus (mu_sieve_machine_t mach, struct mu_locus_range *);
char *mu_sieve_get_daemon_email (mu_sieve_machine_t mach);
const char *mu_sieve_get_identifier (mu_sieve_machine_t mach);
@@ -322,9 +326,13 @@ const char *mu_sieve_type_str (mu_sieve_data_type type);
/* Principal entry points */
int mu_sieve_compile (mu_sieve_machine_t mach, const char *name);
+int mu_sieve_compile_text (mu_sieve_machine_t mach,
+ const char *buf, size_t bufsize,
+ struct mu_locus_point const *pt);
int mu_sieve_compile_buffer (mu_sieve_machine_t mach,
const char *buf, int bufsize,
- const char *fname, int line);
+ const char *fname, int line)
+ MU_DEPRECATED;
int mu_sieve_mailbox (mu_sieve_machine_t mach, mu_mailbox_t mbox);
int mu_sieve_message (mu_sieve_machine_t mach, mu_message_t message);
int mu_sieve_disass (mu_sieve_machine_t mach);
diff --git a/include/mailutils/stream.h b/include/mailutils/stream.h
index f7f58ba..4e82b92 100644
--- a/include/mailutils/stream.h
+++ b/include/mailutils/stream.h
@@ -83,7 +83,7 @@ enum mu_buffer_type
/* Opcodes common for various families */
#define MU_IOCTL_OP_GET 0
#define MU_IOCTL_OP_SET 1
-
+
/* Opcodes for MU_IOCTL_PROGSTREAM */
#define MU_IOCTL_PROG_STATUS 0
#define MU_IOCTL_PROG_PID 1
@@ -106,11 +106,21 @@ enum mu_buffer_type
*/
#define MU_IOCTL_LOGSTREAM_GET_SEVERITY 0
#define MU_IOCTL_LOGSTREAM_SET_SEVERITY 1
+
+ /* The following two subcommands are deprecated and provided for
+ backward compatibility. Please use the MU_IOCTL_LOGSTREAM_GET_LOCUS_RANGE
+ and MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE instead. */
/* Get or set locus.
- Arg: struct mu_locus *
+ Arg: struct mu_locus_DEPRECATED *
*/
-#define MU_IOCTL_LOGSTREAM_GET_LOCUS 2
-#define MU_IOCTL_LOGSTREAM_SET_LOCUS 3
+#define MU_IOCTL_LOGSTREAM_GET_LOCUS_DEPRECATED 2
+#define MU_IOCTL_LOGSTREAM_SET_LOCUS_DEPRECATED 3
+
+int mu_ioctl_logstream_get_locus_deprecated (void) MU_DEPRECATED;
+#define MU_IOCTL_LOGSTREAM_GET_LOCUS mu_ioctl_logstream_get_locus_deprecated ()
+int mu_ioctl_logstream_set_locus_deprecated (void) MU_DEPRECATED;
+#define MU_IOCTL_LOGSTREAM_SET_LOCUS mu_ioctl_logstream_set_locus_deprecated ()
+
/* Get or set log mode.
Arg: int *
*/
@@ -158,6 +168,15 @@ enum mu_buffer_type
Arg: mu_stream_t*
*/
#define MU_IOCTL_LOGSTREAM_CLONE 14
+
+ /* Get locus range.
+ Arg: struct mu_locus_range *
+ */
+#define MU_IOCTL_LOGSTREAM_GET_LOCUS_RANGE 15
+ /* Set locus range.
+ Arg: struct mu_locus_range *
+ */
+#define MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE 16
/* Opcodes for MU_IOCTL_XSCRIPTSTREAM */
/* Swap transcript levels.
diff --git a/include/mailutils/sys/logstream.h b/include/mailutils/sys/logstream.h
index 8bb1c1e..d480110 100644
--- a/include/mailutils/sys/logstream.h
+++ b/include/mailutils/sys/logstream.h
@@ -19,6 +19,7 @@
#include <mailutils/types.h>
#include <mailutils/sys/stream.h>
+#include <mailutils/locus.h>
struct _mu_log_stream
{
@@ -30,7 +31,7 @@ struct _mu_log_stream
int logmode; /* Mode flags */
int sevmask; /* Mask out the output of severity level for
these severities. */
- struct mu_locus locus; /* Location */
+ struct mu_locus_range locrange; /* Location in the source file */
};
void _mu_log_stream_setup (struct _mu_log_stream *sp, mu_stream_t transport);
diff --git a/include/mailutils/types.hin b/include/mailutils/types.hin
index 2a0ee17..e1a9ac4 100644
--- a/include/mailutils/types.hin
+++ b/include/mailutils/types.hin
@@ -149,13 +149,25 @@ typedef unsigned int mu_debug_level_t;
#define MU_DEFAULT_RECORD _MU_DEFAULT_RECORD_
-struct mu_locus
+/* This structure used to be called mu_locus in mailutils up to
+ 3.2.91-46 [release-3.2-71-g719e64a]. It is superseded by
+ structs mu_locus_point and mu_locus_range, defined in
+ <mailutils/locus.h>.
+
+ This definition is provided for backward compatibility. Authors are
+ urged to switch to the new API as soon as their time permits.
+
+ Please see http://mailutils.org/wiki/Source_location_API#Deprecated_interface
+ for detailed guidelines.
+*/
+struct mu_locus_DEPRECATED
{
char *mu_file;
unsigned mu_line;
unsigned mu_col;
};
-
+#define mu_locus mu_locus_DEPRECATED
+
#ifdef __cplusplus
}
#endif
diff --git a/include/mailutils/yyloc.h b/include/mailutils/yyloc.h
new file mode 100644
index 0000000..951ccf0
--- a/dev/null
+++ b/include/mailutils/yyloc.h
@@ -0,0 +1,46 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2017 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _MAILUTILS_YYLOC_H
+#define _MAILUTILS_YYLOC_H
+
+void mu_file_print_locus_point (FILE *,
+ struct mu_locus_point const *lpt);
+void mu_file_print_locus_range (FILE *,
+ struct mu_locus_range const *loc);
+
+#define YYLTYPE struct mu_locus_range
+#define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ { \
+ if (N) \
+ { \
+ (Current).beg = YYRHSLOC(Rhs, 1).beg; \
+ (Current).end = YYRHSLOC(Rhs, N).end; \
+ } \
+ else \
+ { \
+ (Current).beg = YYRHSLOC(Rhs, 0).end; \
+ (Current).end = (Current).beg; \
+ } \
+ } while (0)
+
+#define YY_LOCATION_PRINT(File, Loc) \
+ mu_file_print_locus_range (File, &(Loc))
+
+#endif
+
diff --git a/libmailutils/Makefile.am b/libmailutils/Makefile.am
index a105f38..22aaef6 100644
--- a/libmailutils/Makefile.am
+++ b/libmailutils/Makefile.am
@@ -18,7 +18,7 @@
SUBDIRS = \
auth base address list sockaddr cidr cfg cli diag\
- filter mailbox mailer mime msgset opt server string stream stdstream\
+ filter locus mailbox mailer mime msgset opt server string stream stdstream\
property url imapio datetime . tests
lib_LTLIBRARIES = libmailutils.la
@@ -39,6 +39,7 @@ libmailutils_la_LIBADD = \
filter/libfilter.la\
imapio/libimapio.la\
list/liblist.la\
+ locus/liblocus.la\
mailbox/libmailbox.la\
mailer/libmailer.la\
mime/libmime.la\
diff --git a/libmailutils/base/.gitignore b/libmailutils/base/.gitignore
index e3e0cf0..0b756b1 100644
--- a/libmailutils/base/.gitignore
+++ b/libmailutils/base/.gitignore
@@ -1 +1,2 @@
parsedate.c
+
diff --git a/libmailutils/base/Makefile.am b/libmailutils/base/Makefile.am
index 437dbbe..0936a2d 100644
--- a/libmailutils/base/Makefile.am
+++ b/libmailutils/base/Makefile.am
@@ -54,7 +54,7 @@ libbase_la_SOURCES = \
observer.c\
onexit.c\
opool.c\
- parsedate.c\
+ parsedate.y\
permstr.c\
registrar.c\
refcount.c\
@@ -82,17 +82,10 @@ AM_CPPFLAGS = \
-DLOCALEDIR=\"$(localedir)\"
-YLWRAP = $(SHELL) $(mu_aux_dir)/gylwrap
-AM_YFLAGS=-vt
-AM_LFLAGS=-dp
+YLWRAP = @MU_YLWRAP@
+EXTRA_DIST = gylwrap.conf
+AM_YFLAGS=
+AM_LFLAGS=
-EXTRA_DIST = parsedate.y
-
-BUILT_SOURCES = parsedate.c
-
-parsedate.c: $(srcdir)/parsedate.y
- $(YLWRAP) "$(YACC) $(AM_YFLAGS)" $< \
- y.tab.c parsedate.c y.output parsedate.y.output \
- -- -yy pd_yy
diff --git a/libmailutils/base/assoc.c b/libmailutils/base/assoc.c
index b0e353d..a597ca4 100644
--- a/libmailutils/base/assoc.c
+++ b/libmailutils/base/assoc.c
@@ -387,7 +387,9 @@ mu_assoc_lookup_ref (mu_assoc_t assoc, const char *name, void *dataptr)
}
int
-mu_assoc_install_ref (mu_assoc_t assoc, const char *name, void *pval)
+mu_assoc_install_ref2 (mu_assoc_t assoc, const char *name,
+ void *ret_val,
+ const char **ret_name)
{
int rc;
int inst;
@@ -425,11 +427,20 @@ mu_assoc_install_ref (mu_assoc_t assoc, const char *name, void *pval)
assoc_elem_link (assoc, idx);
}
- *(void**)pval = &assoc->tab[idx]->data;
+ *(void**)ret_val = &assoc->tab[idx]->data;
+ if (ret_name)
+ *ret_name = assoc->tab[idx]->name;
+
return inst ? 0 : MU_ERR_EXISTS;
}
int
+mu_assoc_install_ref (mu_assoc_t assoc, const char *name, void *pval)
+{
+ return mu_assoc_install_ref2 (assoc, name, pval, NULL);
+}
+
+int
mu_assoc_remove (mu_assoc_t assoc, const char *name)
{
int rc;
diff --git a/libmailutils/base/copyfile.c b/libmailutils/base/copyfile.c
index 9a72228..16518ab 100644
--- a/libmailutils/base/copyfile.c
+++ b/libmailutils/base/copyfile.c
@@ -163,7 +163,7 @@ copy_regular_file (const char *srcpath, const char *dstpath, int flags,
rc = mu_stream_ioctl (dst, MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET, trans);
if (rc == 0)
{
- if (fchmod ((int) trans[0], mode))
+ if (fchmod ((int) (intptr_t) trans[0], mode))
{
mu_debug (MU_DEBCAT_STREAM, MU_DEBUG_ERROR,
(_("%s: cannot chmod: %s"),
@@ -193,7 +193,7 @@ copy_regular_file (const char *srcpath, const char *dstpath, int flags,
if (gid != -1)
{
- if (fchown ((int) trans[0], uid, gid))
+ if (fchown ((int) (intptr_t) trans[0], uid, gid))
{
mu_debug (MU_DEBCAT_STREAM, MU_DEBUG_ERROR,
(_("%s: cannot chown to %lu.%lu: %s"),
diff --git a/libmailutils/base/gylwrap.conf b/libmailutils/base/gylwrap.conf
new file mode 100644
index 0000000..33b8c12
--- a/dev/null
+++ b/libmailutils/base/gylwrap.conf
@@ -0,0 +1,3 @@
+# Configuration settings for gylwrap.
+# See ../../mu-aux/gylwrap --help, for details.
+yyrepl = pd_yy
diff --git a/libmailutils/base/wicket.c b/libmailutils/base/wicket.c
index bb5ad2e..1acecff 100644
--- a/libmailutils/base/wicket.c
+++ b/libmailutils/base/wicket.c
@@ -248,7 +248,7 @@ _file_wicket_get_ticket (mu_wicket_t wicket, void *data,
}
int
-mu_wicket_stream_match_url (mu_stream_t stream, struct mu_locus *loc,
+mu_wicket_stream_match_url (mu_stream_t stream, struct mu_locus_point *loc,
mu_url_t url, int parse_flags,
mu_url_t *pticket_url)
{
@@ -329,7 +329,7 @@ mu_wicket_file_match_url (const char *name, mu_url_t url,
{
mu_stream_t stream;
int rc;
- struct mu_locus loc;
+ struct mu_locus_point loc;
rc = mu_file_stream_create (&stream, name, MU_STREAM_READ);
if (rc)
diff --git a/libmailutils/cfg/.gitignore b/libmailutils/cfg/.gitignore
index 8993e60..97bc813 100644
--- a/libmailutils/cfg/.gitignore
+++ b/libmailutils/cfg/.gitignore
@@ -1,3 +1,4 @@
lexer.c
parser.c
parser.h
+parser.output
diff --git a/libmailutils/cfg/Makefile.am b/libmailutils/cfg/Makefile.am
index d2d3f44..eb299fa 100644
--- a/libmailutils/cfg/Makefile.am
+++ b/libmailutils/cfg/Makefile.am
@@ -20,8 +20,8 @@ noinst_LTLIBRARIES = libcfg.la
libcfg_la_SOURCES = \
driver.c\
format.c\
- lexer.c\
- parser.c
+ lexer.l\
+ parser.y
localedir = $(datadir)/locale
AM_CPPFLAGS = \
@@ -29,25 +29,15 @@ AM_CPPFLAGS = \
-DSYSCONFDIR=\"$(sysconfdir)\"\
-DLOCALEDIR=\"$(localedir)\"
-
EXTRA_DIST = \
lexer.l\
parser.y\
- parser.h
+ parser.h\
+ gylwrap.conf
BUILT_SOURCES = parser.c parser.h lexer.c
-YLWRAP = $(SHELL) $(mu_aux_dir)/gylwrap
-AM_YFLAGS=-vt
+YLWRAP = @MU_YLWRAP@
+AM_YFLAGS=-vdt
AM_LFLAGS=-dp
-parser.c parser.h: $(srcdir)/parser.y
- $(YLWRAP) "$(YACC) $(AM_YFLAGS) -d" $< \
- y.tab.c parser.c y.tab.h parser.h \
- y.output parser.y.output \
- -- -yy mu_cfg_yy
-
-lexer.c: $(srcdir)/lexer.l parser.h
- $(YLWRAP) "$(LEX) $(AM_LFLAGS) $(LFLAGS)" \
- $(srcdir)/lexer.l lex.yy.c lexer.c \
- -- -yy mu_cfg_yy
diff --git a/libmailutils/cfg/format.c b/libmailutils/cfg/format.c
index a751c57..78d84b1 100644
--- a/libmailutils/cfg/format.c
+++ b/libmailutils/cfg/format.c
@@ -152,10 +152,10 @@ format_node (const mu_cfg_node_t *node, void *data)
{
struct tree_print *tp = data;
- if ((tp->flags & MU_CF_FMT_LOCUS) && node->locus.mu_file)
+ if ((tp->flags & MU_CF_FMT_LOCUS) && node->locus.beg.mu_file)
mu_stream_printf (tp->stream, "# %lu \"%s\"\n",
- (unsigned long) node->locus.mu_line,
- node->locus.mu_file);
+ (unsigned long) node->locus.beg.mu_line,
+ node->locus.beg.mu_file);
format_level (tp->stream, tp->level);
switch (node->type)
{
diff --git a/libmailutils/cfg/gylwrap.conf b/libmailutils/cfg/gylwrap.conf
new file mode 100644
index 0000000..4a93e6f
--- a/dev/null
+++ b/libmailutils/cfg/gylwrap.conf
@@ -0,0 +1,4 @@
+# Configuration settings for gylwrap.
+# See ../../mu-aux/gylwrap --help, for details.
+
+yyrepl = mu_cfg_yy
diff --git a/libmailutils/cfg/lexer.l b/libmailutils/cfg/lexer.l
index 88f2486..0465196 100644
--- a/libmailutils/cfg/lexer.l
+++ b/libmailutils/cfg/lexer.l
@@ -38,7 +38,10 @@
#include <mailutils/cfg.h>
#include <mailutils/list.h>
#include <mailutils/util.h>
-
+#include <mailutils/locus.h>
+#include <mailutils/stream.h>
+#include <mailutils/stdstream.h>
+#include <mailutils/yyloc.h>
#include "parser.h"
void _mu_line_begin (void);
@@ -66,7 +69,16 @@ static int (*char_to_strip)(char); /* Strip matching characters of each
static int isemptystr(int off);
static mu_opool_t pool;
-
+static mu_linetrack_t trk;
+static struct mu_locus_point string_beg;
+#define YY_USER_ACTION \
+ do \
+ { \
+ mu_linetrack_advance (trk, &yylloc, yytext, yyleng); \
+ mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, \
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &yylloc); \
+ } \
+ while (0);
%}
%option nounput
@@ -83,7 +95,7 @@ P [1-9][0-9]*
"/*" BEGIN(COMMENT);
<COMMENT>[^*\n]* /* eat anything that's not a '*' */
<COMMENT>"*"+[^*/\n]* /* eat up '*'s not followed by '/'s */
-<COMMENT>\n ++mu_cfg_locus.mu_line;
+<COMMENT>\n ;
<COMMENT>"*"+"/" BEGIN (INITIAL);
/* End-of-line comments */
#debug=.*\n {
@@ -91,9 +103,9 @@ P [1-9][0-9]*
mu_cfg_set_debug ();
mu_cfg_set_lex_debug ();
}
-#.*\n { mu_cfg_locus.mu_line++; }
+#.*\n ;
#.* /* end-of-file comment */;
-"//".*\n { mu_cfg_locus.mu_line++; }
+"//".*\n ;
"//".* /* end-of-file comment */;
/* Identifiers */
<INITIAL>{ID} {
@@ -113,6 +125,7 @@ P [1-9][0-9]*
return MU_TOK_QSTRING; }
\"[^\\"\n]*\\. |
\"[^\\"\n]*\\\n { BEGIN (STR);
+ mu_locus_point_copy (&string_beg, &yylloc.beg);
_mu_line_begin ();
_mu_line_add_unescape_last (yytext + 1, yyleng - 1); }
<STR>[^\\"\n]*\\. |
@@ -121,6 +134,10 @@ P [1-9][0-9]*
if (yyleng > 1)
_mu_line_add (yytext, yyleng - 1);
yylval.string = _mu_line_finish ();
+
+ mu_locus_point_copy (&yylloc.beg, &string_beg);
+ mu_locus_point_deinit (&string_beg);
+
return MU_TOK_QSTRING; }
/* Multiline strings */
"<<"(-" "?)?\\?{ID}[ \t]*#.*\n |
@@ -130,8 +147,8 @@ P [1-9][0-9]*
"<<"(-" "?)?\"{ID}\"[ \t]*"//".*\n |
"<<"(-" "?)?\"{ID}\"[ \t]*\n {
BEGIN (ML);
+ mu_locus_point_copy (&string_beg, &yylloc.beg);
multiline_begin (yytext+2);
- mu_cfg_locus.mu_line++;
}
<ML>.*\n { char *p = multiline_strip_tabs (yytext);
@@ -142,21 +159,21 @@ P [1-9][0-9]*
multiline_delimiter = NULL;
BEGIN (INITIAL);
yylval.string = multiline_finish ();
+
+ mu_locus_point_copy (&yylloc.beg, &string_beg);
+ mu_locus_point_deinit (&string_beg);
+ /* FIXME: Adjust yylloc.end without retreating trk */
return MU_TOK_MSTRING;
}
- mu_cfg_locus.mu_line++;
multiline_add (p); }
{WS} ;
/* Other tokens */
-\n { mu_cfg_locus.mu_line++; }
+\n ;
[,;{}()] return yytext[0];
. { if (mu_isprint (yytext[0]))
- mu_diag_at_locus (MU_LOG_ERROR, &mu_cfg_locus,
- _("stray character %c"), yytext[0]);
+ mu_error (_("stray character %c"), yytext[0]);
else
- mu_diag_at_locus (MU_LOG_ERROR, &mu_cfg_locus,
- _("stray character \\%03o"),
- (unsigned char) yytext[0]);
+ mu_error (_("stray character \\%03o"), (unsigned char) yytext[0]);
mu_cfg_error_count++;
}
%%
@@ -175,8 +192,7 @@ unescape_to_line (int c)
char t = mu_wordsplit_c_unquote_char (c);
if (t == c && t != '\\' && t != '\"')
{
- mu_diag_at_locus (MU_LOG_ERROR, &mu_cfg_locus,
- _("unknown escape sequence '\\%c'"), c);
+ mu_error (_("unknown escape sequence '\\%c'"), c);
mu_cfg_error_count++;
}
mu_opool_append_char (pool, t);
@@ -365,29 +381,24 @@ mu_cfg_parse_file (mu_cfg_tree_t **return_tree, const char *file, int flags)
mu_cfg_set_lex_debug ();
- /* Initialize locus: */
- /* 1. Save file name in the lexer object pool and point `file' member
- to this copy. Free full_name: it is not used after that. */
- _mu_line_begin ();
- _mu_line_add (full_name, strlen (full_name));
- mu_cfg_locus.mu_file = _mu_line_finish ();
- free (full_name);
- /* 2. Initialize line number */
- mu_cfg_locus.mu_line = 1;
-
+ /* Initialize tracker */
+ mu_linetrack_create (&trk, full_name, 2);
+ memset (&string_beg, 0, sizeof string_beg);
/* Parse configuration */
yyrestart (fp);
rc = mu_cfg_parse (return_tree);
fclose (fp);
if (flags & MU_CF_VERBOSE)
- mu_diag_output (MU_DIAG_INFO, _("finished parsing file `%s'"),
- mu_cfg_locus.mu_file);
-
+ mu_diag_output (MU_DIAG_INFO, _("finished parsing file `%s'"), full_name);
+ free (full_name);
+ mu_linetrack_destroy (&trk);
+ mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, NULL);
return rc == 0 ? 0 : MU_ERR_FAILURE;
}
mu_opool_t
-mu_cfg_lexer_pool ()
+mu_cfg_lexer_pool (void)
{
mu_opool_t p = pool;
pool = NULL;
diff --git a/libmailutils/cfg/parser.y b/libmailutils/cfg/parser.y
index 80b940f..4503c77 100644
--- a/libmailutils/cfg/parser.y
+++ b/libmailutils/cfg/parser.y
@@ -40,10 +40,10 @@
#include <mailutils/stream.h>
#include <mailutils/stdstream.h>
#include <mailutils/cidr.h>
+#include <mailutils/yyloc.h>
int mu_cfg_parser_verbose;
static mu_list_t /* of mu_cfg_node_t */ parse_node_list;
-struct mu_locus mu_cfg_locus;
size_t mu_cfg_error_count;
static int _mu_cfg_errcnt;
@@ -57,7 +57,7 @@ char *_mu_line_finish (void);
static int
yyerror (char *s)
{
- mu_diag_at_locus (MU_LOG_ERROR, &mu_cfg_locus, "%s", s);
+ mu_error ("%s", s);
mu_cfg_error_count++;
return 0;
}
@@ -85,7 +85,7 @@ _node_set_parent (void *item, void *data)
}
static mu_cfg_node_t *
-mu_cfg_alloc_node (enum mu_cfg_node_type type, struct mu_locus *loc,
+mu_cfg_alloc_node (enum mu_cfg_node_type type, struct mu_locus_range *loc,
const char *tag, mu_config_value_t *label,
mu_list_t nodelist)
{
@@ -94,7 +94,8 @@ mu_cfg_alloc_node (enum mu_cfg_node_type type, struct mu_locus *loc,
size_t size = sizeof *np + strlen (tag) + 1;
np = mu_alloc (size);
np->type = type;
- np->locus = *loc;
+ mu_locus_range_init (&np->locus);
+ mu_locus_range_copy (&np->locus, loc);
p = (char*) (np + 1);
np->tag = p;
strcpy (p, tag);
@@ -121,17 +122,15 @@ debug_print_node (mu_cfg_node_t *node)
if (node->type == mu_cfg_node_undefined)
{
/* Stay on the safe side */
- mu_diag_at_locus (MU_LOG_ERROR, &mu_cfg_locus,
- _("unknown statement type!"));
+ mu_error (_("unknown statement type!"));
mu_cfg_error_count++;
}
else
{
/* FIXME: How to print label? */
- mu_diag_at_locus (MU_LOG_DEBUG, &node->locus,
- "statement: %s, id: %s",
- node_type_str (node->type),
- node->tag ? node->tag : "(null)");
+ mu_error ("statement: %s, id: %s",
+ node_type_str (node->type),
+ node->tag ? node->tag : "(null)");
}
}
}
@@ -170,6 +169,9 @@ mu_cfg_create_node_list (mu_list_t *plist)
%}
+%locations
+%expect 1
+
%union {
mu_cfg_node_t node;
mu_cfg_node_t *pnode;
@@ -177,7 +179,6 @@ mu_cfg_create_node_list (mu_list_t *plist)
char *string;
mu_config_value_t value, *pvalue;
mu_list_t list;
- struct { const char *name; struct mu_locus locus; } ident;
}
%token <string> MU_TOK_IDENT MU_TOK_STRING MU_TOK_QSTRING MU_TOK_MSTRING
@@ -186,7 +187,7 @@ mu_cfg_create_node_list (mu_list_t *plist)
%type <value> value
%type <pvalue> tag vallist
%type <list> values list vlist
-%type <ident> ident
+%type <string> ident
%type <nodelist> stmtlist
%type <pnode> stmt simple block
@@ -217,32 +218,32 @@ stmt : simple
simple : ident vallist ';'
{
- $$ = mu_cfg_alloc_node (mu_cfg_node_param, &$1.locus,
- $1.name, $2,
- NULL);
+ struct mu_locus_range lr;
+ lr.beg = @1.beg;
+ lr.end = @3.end;
+ $$ = mu_cfg_alloc_node (mu_cfg_node_param, &lr, $1, $2, NULL);
}
;
block : ident tag '{' '}' opt_sc
{
- $$ = mu_cfg_alloc_node (mu_cfg_node_statement, &$1.locus,
- $1.name, $2,
- NULL);
+ struct mu_locus_range lr;
+ lr.beg = @1.beg;
+ lr.end = @5.end;
+ $$ = mu_cfg_alloc_node (mu_cfg_node_statement, &lr, $1, $2, NULL);
}
| ident tag '{' stmtlist '}' opt_sc
{
- $$ = mu_cfg_alloc_node (mu_cfg_node_statement, &$1.locus,
- $1.name, $2, $4);
+ struct mu_locus_range lr;
+ lr.beg = @1.beg;
+ lr.end = @6.end;
+ $$ = mu_cfg_alloc_node (mu_cfg_node_statement, &lr, $1, $2, $4);
mu_list_foreach ($4, _node_set_parent, $$);
}
;
ident : MU_TOK_IDENT
- {
- $$.name = $1;
- $$.locus = mu_cfg_locus;
- }
- ;
+ ;
tag : /* empty */
{
@@ -270,8 +271,7 @@ vallist : vlist
val.v.arg.v = mu_alloc (n * sizeof (val.v.arg.v[0]));
if (!val.v.arg.v)
{
- mu_diag_at_locus (MU_LOG_ERROR, &mu_cfg_locus,
- _("not enough memory"));
+ mu_error (_("not enough memory"));
abort();
}
@@ -292,9 +292,7 @@ vlist : value
int rc = mu_list_create (&$$);
if (rc)
{
- mu_diag_at_locus (MU_LOG_ERROR, &mu_cfg_locus,
- _("cannot create list: %s"),
- mu_strerror (rc));
+ mu_error (_("cannot create list: %s"), mu_strerror (rc));
abort ();
}
mu_list_append ($$, config_value_dup (&$1)); /* FIXME */
@@ -401,14 +399,15 @@ mu_cfg_parse (mu_cfg_tree_t **ptree)
mu_cfg_tree_t *tree;
mu_opool_t pool;
int save_mode = 0, mode;
- struct mu_locus save_locus = { NULL, };
+ struct mu_locus_range save_locus = MU_LOCUS_RANGE_INITIALIZER;
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, MU_IOCTL_LOGSTREAM_GET_MODE,
&save_mode);
mode = save_mode | MU_LOGMODE_LOCUS;
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, MU_IOCTL_LOGSTREAM_SET_MODE,
&mode);
- mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, MU_IOCTL_LOGSTREAM_GET_LOCUS,
+ mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_GET_LOCUS_RANGE,
&save_locus);
mu_cfg_set_debug ();
@@ -432,9 +431,10 @@ mu_cfg_parse (mu_cfg_tree_t **ptree)
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, MU_IOCTL_LOGSTREAM_SET_MODE,
&save_mode);
- mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, MU_IOCTL_LOGSTREAM_SET_LOCUS,
+ mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE,
&save_locus);
- free (save_locus.mu_file);
+ mu_locus_range_deinit (&save_locus); /* FIXME: refcount? */
return rc;
}
@@ -480,7 +480,7 @@ mu_cfg_tree_union (mu_cfg_tree_t **pa, mu_cfg_tree_t **pb)
static mu_cfg_tree_t *
do_include (const char *name, struct mu_cfg_parse_hints *hints,
- struct mu_locus *loc)
+ struct mu_locus_range const *loc)
{
struct stat sb;
char *tmpname = NULL;
@@ -520,15 +520,15 @@ do_include (const char *name, struct mu_cfg_parse_hints *hints,
}
else if (errno == ENOENT)
{
- mu_diag_at_locus (MU_LOG_ERROR, loc,
- _("include file or directory does not exist"));
+ mu_diag_at_locus_range (MU_LOG_ERROR, loc,
+ _("include file or directory does not exist"));
mu_cfg_error_count++;
}
else
{
- mu_diag_at_locus (MU_LOG_ERROR, loc,
- _("cannot stat include file or directory: %s"),
- mu_strerror (errno));
+ mu_diag_at_locus_range (MU_LOG_ERROR, loc,
+ _("cannot stat include file or directory: %s"),
+ mu_strerror (errno));
mu_cfg_error_count++;
}
@@ -576,7 +576,7 @@ mu_cfg_tree_postprocess (mu_cfg_tree_t *tree, struct mu_cfg_parse_hints *hints)
}
else
{
- mu_diag_at_locus (MU_LOG_ERROR, &mu_cfg_locus,
+ mu_diag_at_locus_range (MU_LOG_ERROR, &node->locus,
_("argument to `program' is not a string"));
mu_cfg_error_count++;
mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
@@ -602,7 +602,7 @@ mu_cfg_tree_postprocess (mu_cfg_tree_t *tree, struct mu_cfg_parse_hints *hints)
}
else
{
- mu_diag_at_locus (MU_LOG_ERROR, &mu_cfg_locus,
+ mu_diag_at_locus_range (MU_LOG_ERROR, &node->locus,
_("argument to `include' is not a string"));
mu_cfg_error_count++;
}
@@ -760,8 +760,7 @@ push_section (struct scan_tree_data *dat, struct mu_cfg_section *sec)
struct mu_cfg_section_list *p = mu_alloc (sizeof *p);
if (!p)
{
- mu_diag_at_locus (MU_LOG_ERROR, &mu_cfg_locus,
- _("not enough memory"));
+ mu_error (_("not enough memory"));
mu_cfg_error_count++;
return 1;
}
@@ -782,7 +781,7 @@ pop_section (struct scan_tree_data *dat)
}
static int
-valcvt (const struct mu_locus *locus,
+valcvt (const struct mu_locus_range *locus,
void *tgt, mu_c_type_t type, mu_config_value_t *val)
{
int rc;
@@ -790,7 +789,7 @@ valcvt (const struct mu_locus *locus,
if (val->type != MU_CFG_STRING)
{
- mu_diag_at_locus (MU_LOG_ERROR, locus, _("expected string value"));
+ mu_diag_at_locus_range (MU_LOG_ERROR, locus, _("expected string value"));
mu_cfg_error_count++;
return 1;
}
@@ -798,8 +797,8 @@ valcvt (const struct mu_locus *locus,
rc = mu_str_to_c (val->v.string, type, tgt, &errmsg);
if (rc)
{
- mu_diag_at_locus (MU_LOG_ERROR, locus, "%s",
- errmsg ? errmsg : mu_strerror (rc));
+ mu_diag_at_locus_range (MU_LOG_ERROR, locus, "%s",
+ errmsg ? errmsg : mu_strerror (rc));
free (errmsg);
}
return rc;
@@ -810,7 +809,7 @@ struct set_closure
mu_list_t list;
int type;
struct scan_tree_data *sdata;
- const struct mu_locus *locus;
+ const struct mu_locus_range *locus;
};
static size_t config_type_size[] = {
@@ -840,7 +839,7 @@ _set_fun (void *item, void *data)
if ((size_t) clos->type >= MU_ARRAY_SIZE(config_type_size)
|| (size = config_type_size[clos->type]) == 0)
{
- mu_diag_at_locus (MU_LOG_EMERG, clos->locus,
+ mu_diag_at_locus_range (MU_LOG_EMERG, clos->locus,
_("INTERNAL ERROR at %s:%d: unhandled data type %d"),
__FILE__, __LINE__, clos->type);
mu_cfg_error_count++;
@@ -850,7 +849,8 @@ _set_fun (void *item, void *data)
tgt = mu_alloc (size);
if (!tgt)
{
- mu_diag_at_locus (MU_LOG_ERROR, clos->locus, _("not enough memory"));
+ mu_diag_at_locus_range (MU_LOG_ERROR, clos->locus,
+ _("not enough memory"));
mu_cfg_error_count++;
return 1;
}
@@ -870,9 +870,9 @@ parse_param (struct scan_tree_data *sdata, const mu_cfg_node_t *node)
if (!param)
{
- mu_diag_at_locus (MU_LOG_ERROR, &node->locus,
- _("unknown keyword `%s'"),
- node->tag);
+ mu_diag_at_locus_range (MU_LOG_ERROR, &node->locus,
+ _("unknown keyword `%s'"),
+ node->tag);
mu_cfg_error_count++;
return 1;
}
@@ -887,7 +887,7 @@ parse_param (struct scan_tree_data *sdata, const mu_cfg_node_t *node)
tgt = NULL;
else
{
- mu_diag_at_locus (MU_LOG_EMERG, &node->locus,
+ mu_diag_at_locus_range (MU_LOG_EMERG, &node->locus,
_("INTERNAL ERROR: cannot determine target offset for "
"%s"), param->ident);
abort ();
@@ -915,7 +915,7 @@ parse_param (struct scan_tree_data *sdata, const mu_cfg_node_t *node)
break;
case MU_CFG_ARRAY:
- mu_diag_at_locus (MU_LOG_ERROR, &node->locus,
+ mu_diag_at_locus_range (MU_LOG_ERROR, &node->locus,
_("expected list, but found array"));
mu_cfg_error_count++;
return 1;
@@ -929,13 +929,13 @@ parse_param (struct scan_tree_data *sdata, const mu_cfg_node_t *node)
{
if (!param->callback)
{
- mu_diag_at_locus (MU_LOG_EMERG, &node->locus,
+ mu_diag_at_locus_range (MU_LOG_EMERG, &node->locus,
_("INTERNAL ERROR: %s: callback not defined"),
node->tag);
abort ();
}
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
- MU_IOCTL_LOGSTREAM_SET_LOCUS,
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE,
(void*) &node->locus);
if (param->callback (tgt, node->label))
return 1;
@@ -964,9 +964,9 @@ _scan_tree_helper (const mu_cfg_node_t *node, void *data)
{
if (mu_cfg_parser_verbose)
{
- mu_diag_at_locus (MU_LOG_WARNING, &node->locus,
- _("unknown section `%s'"),
- node->tag);
+ mu_diag_at_locus_range (MU_LOG_WARNING, &node->locus,
+ _("unknown section `%s'"),
+ node->tag);
}
return MU_CFG_ITER_SKIP;
}
@@ -983,7 +983,7 @@ _scan_tree_helper (const mu_cfg_node_t *node, void *data)
if (sec->parser)
{
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
- MU_IOCTL_LOGSTREAM_SET_LOCUS,
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE,
(void*) &node->locus);
if (sec->parser (mu_cfg_section_start, node,
sec->label, &sec->target,
@@ -1041,7 +1041,7 @@ mu_cfg_scan_tree (mu_cfg_tree_t *tree, struct mu_cfg_section *sections,
struct scan_tree_data dat;
struct mu_cfg_iter_closure clos;
int save_mode = 0, mode;
- struct mu_locus save_locus = { NULL, };
+ struct mu_locus_range save_locus = MU_LOCUS_RANGE_INITIALIZER;
int rc;
dat.tree = tree;
@@ -1056,7 +1056,7 @@ mu_cfg_scan_tree (mu_cfg_tree_t *tree, struct mu_cfg_section *sections,
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
- MU_IOCTL_LOGSTREAM_GET_LOCUS, &save_locus);
+ MU_IOCTL_LOGSTREAM_GET_LOCUS_RANGE, &save_locus);
if (push_section (&dat, sections))
return 1;
@@ -1070,8 +1070,7 @@ mu_cfg_scan_tree (mu_cfg_tree_t *tree, struct mu_cfg_section *sections,
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_SET_MODE, &save_mode);
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
- MU_IOCTL_LOGSTREAM_SET_LOCUS, &save_locus);
- free (save_locus.mu_file);
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &save_locus);
return dat.error;
}
@@ -1124,7 +1123,7 @@ mu_cfg_tree_create (struct mu_cfg_tree **ptree)
mu_cfg_node_t *
mu_cfg_tree_create_node (struct mu_cfg_tree *tree,
enum mu_cfg_node_type type,
- const struct mu_locus *loc,
+ const struct mu_locus_range *loc,
const char *tag, const char *label,
mu_list_t nodelist)
{
@@ -1136,7 +1135,7 @@ mu_cfg_tree_create_node (struct mu_cfg_tree *tree,
np = mu_alloc (size);
np->type = type;
if (loc)
- np->locus = *loc;
+ mu_locus_range_copy (&np->locus, loc);
else
memset (&np->locus, 0, sizeof np->locus);
p = (char*) (np + 1);
@@ -1478,11 +1477,7 @@ mu_cfg_create_subtree (const char *path, mu_cfg_node_t **pnode)
char **argv;
enum mu_cfg_node_type type;
mu_cfg_node_t *node = NULL;
- struct mu_locus locus;
-
- locus.mu_file = "<int>";
- locus.mu_line = 0;
- locus.mu_col = 0;
+ struct mu_locus_range locus = MU_LOCUS_RANGE_INITIALIZER;
rc = split_cfg_path (path, &argc, &argv);
if (rc)
diff --git a/libmailutils/diag/diag.c b/libmailutils/diag/diag.c
index 318afe0..b5a7482 100644
--- a/libmailutils/diag/diag.c
+++ b/libmailutils/diag/diag.c
@@ -29,6 +29,7 @@
#include <mailutils/errno.h>
#include <mailutils/stdstream.h>
#include <mailutils/stream.h>
+#include <mailutils/locus.h>
void
mu_diag_init ()
@@ -56,17 +57,52 @@ mu_diag_output (int level, const char *fmt, ...)
}
void
-mu_diag_at_locus (int level, struct mu_locus const *loc, const char *fmt, ...)
+mu_vdiag_at_locus_range (int level, struct mu_locus_range const *loc,
+ const char *fmt, va_list ap)
+{
+ struct mu_locus_range old = MU_LOCUS_RANGE_INITIALIZER;
+ int restore = 0;
+
+ if (loc)
+ {
+ if (mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_GET_LOCUS_RANGE, &old) == 0)
+ {
+ mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, (void*) loc);
+ restore = 1;
+ }
+ }
+
+ mu_diag_voutput (level, fmt, ap);
+
+ if (restore)
+ {
+ mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &old);
+ mu_locus_range_deinit (&old);
+ }
+}
+
+void
+mu_diag_at_locus_range (int level, struct mu_locus_range const *loc,
+ const char *fmt, ...)
{
va_list ap;
+ va_start (ap, fmt);
+ mu_vdiag_at_locus_range (level, loc, fmt, ap);
+ va_end (ap);
+}
+void
+mu_diag_at_locus_point (int level, struct mu_locus_point const *loc,
+ const char *fmt, ...)
+{
+ va_list ap;
+ struct mu_locus_range lr = MU_LOCUS_RANGE_INITIALIZER;
+ lr.beg = *loc;
va_start (ap, fmt);
- if (loc && loc->mu_file)
- mu_stream_printf (mu_strerr, "\033f<%d>%s\033l<%u>\033c<%u>",
- (unsigned) strlen (loc->mu_file), loc->mu_file,
- loc->mu_line,
- loc->mu_col);
- mu_diag_voutput (level, fmt, ap);
+ mu_vdiag_at_locus_range (level, &lr, fmt, ap);
va_end (ap);
}
diff --git a/libmailutils/locus/Makefile.am b/libmailutils/locus/Makefile.am
new file mode 100644
index 0000000..8a9f384
--- a/dev/null
+++ b/libmailutils/locus/Makefile.am
@@ -0,0 +1,31 @@
+# GNU Mailutils -- a suite of utilities for electronic mail
+# Copyright (C) 2017 Free Software Foundation, Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 3 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General
+# Public License along with this library. If not, see
+# <http://www.gnu.org/licenses/>.
+
+noinst_LTLIBRARIES = liblocus.la
+
+liblocus_la_SOURCES = \
+ ident.c\
+ debug.c\
+ linetrack.c\
+ locus.c\
+ filprloc.c\
+ strprloc.c
+
+EXTRA_DIST = genprloc.c
+
+AM_CPPFLAGS = @MU_LIB_COMMON_INCLUDES@ -I/libmailutils
+
diff --git a/libmailutils/locus/debug.c b/libmailutils/locus/debug.c
new file mode 100644
index 0000000..3e95af1
--- a/dev/null
+++ b/libmailutils/locus/debug.c
@@ -0,0 +1,74 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2017 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <mailutils/types.h>
+#include <mailutils/locus.h>
+#include <mailutils/error.h>
+#include <mailutils/errno.h>
+#include <mailutils/diag.h>
+#include <mailutils/stream.h>
+#include <mailutils/stdstream.h>
+
+void
+mu_stream_vlprintf (mu_stream_t stream,
+ struct mu_locus_range const *loc,
+ char const *fmt, va_list ap)
+{
+ mu_stream_print_locus_range (stream, loc);
+ mu_stream_write (stream, ": ", 2, NULL);
+ mu_stream_vprintf (stream, fmt, ap);
+}
+
+void
+mu_stream_lprintf (mu_stream_t stream,
+ struct mu_locus_range const *loc,
+ char const *fmt, ...)
+{
+ va_list ap;
+ va_start (ap, fmt);
+ mu_stream_vlprintf (stream, loc, fmt, ap);
+ va_end (ap);
+}
+
+void
+mu_lrange_debug (struct mu_locus_range const *loc,
+ char const *fmt, ...)
+{
+ va_list ap;
+ int rc, mode;
+
+ rc = mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_GET_MODE, &mode);
+ if (rc == 0)
+ {
+ int new_mode = mode & ~MU_LOGMODE_LOCUS;
+ rc = mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_MODE, &new_mode);
+ }
+
+ va_start (ap, fmt);
+ 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,
+ MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
+
+}
diff --git a/libmailutils/locus/filprloc.c b/libmailutils/locus/filprloc.c
new file mode 100644
index 0000000..e1cdfa4
--- a/dev/null
+++ b/libmailutils/locus/filprloc.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+#define STREAM_TYPE FILE*
+#define STREAM_PRINTF fprintf
+#define PRINT_LOCUS_POINT mu_file_print_locus_point
+#define PRINT_LOCUS_RANGE mu_file_print_locus_range
+#include "genprloc.c"
diff --git a/libmailutils/locus/genprloc.c b/libmailutils/locus/genprloc.c
new file mode 100644
index 0000000..cc15030
--- a/dev/null
+++ b/libmailutils/locus/genprloc.c
@@ -0,0 +1,71 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2017 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef STREAM_TYPE
+# error "STREAM_TYPE not defined"
+#endif
+#ifndef PRINT_LOCUS_POINT
+# error "PRINT_LOCUS_POINT not defined"
+#endif
+#ifndef PRINT_LOCUS_RANGE
+# error "PRINT_LOCUS_RANGE not defined"
+#endif
+#ifndef STREAM_PRINTF
+# error "STREAM_PRINTF not defined"
+#endif
+
+#include <mailutils/types.h>
+#include <mailutils/locus.h>
+
+void
+PRINT_LOCUS_POINT (STREAM_TYPE stream, struct mu_locus_point const *lp)
+{
+ if (lp->mu_file)
+ {
+ STREAM_PRINTF (stream, "%s:%u",
+ lp->mu_file, lp->mu_line);
+ if (lp->mu_col)
+ STREAM_PRINTF (stream, ".%u", lp->mu_col);
+ }
+}
+
+void
+PRINT_LOCUS_RANGE (STREAM_TYPE stream, struct mu_locus_range const *loc)
+{
+ PRINT_LOCUS_POINT (stream, &loc->beg);
+ if (loc->end.mu_file)
+ {
+ if (!mu_locus_point_same_file (&loc->beg, &loc->end))
+ {
+ STREAM_PRINTF (stream, "-");
+ PRINT_LOCUS_POINT (stream, &loc->end);
+ }
+ else if (loc->beg.mu_line != loc->end.mu_line)
+ {
+ STREAM_PRINTF (stream, "-");
+ STREAM_PRINTF (stream, "%u", loc->end.mu_line);
+ if (loc->end.mu_col)
+ STREAM_PRINTF (stream, ".%u", loc->end.mu_col);
+ }
+ else if (loc->beg.mu_col
+ && loc->beg.mu_col != loc->end.mu_col)
+ {
+ STREAM_PRINTF (stream, "-");
+ STREAM_PRINTF (stream, "%u", loc->end.mu_col);
+ }
+ }
+}
diff --git a/libmailutils/locus/ident.c b/libmailutils/locus/ident.c
new file mode 100644
index 0000000..cb7591e
--- a/dev/null
+++ b/libmailutils/locus/ident.c
@@ -0,0 +1,152 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2017 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+#include <mailutils/types.h>
+#include <mailutils/assoc.h>
+#include <mailutils/locus.h>
+#include <mailutils/error.h>
+#include <mailutils/errno.h>
+#include <mailutils/diag.h>
+#include <mailutils/list.h>
+#include <mailutils/io.h>
+#include <mailutils/stream.h>
+#include <mailutils/iterator.h>
+
+struct mu_ident_ref
+{
+ size_t count;
+};
+
+static mu_assoc_t nametab;
+
+int
+mu_ident_ref (char const *name, char const **refname)
+{
+ int rc;
+ struct mu_ident_ref *ref, **refptr;
+
+ if (!refname)
+ return MU_ERR_OUT_PTR_NULL;
+ if (!name)
+ {
+ *refname = NULL;
+ return 0;
+ }
+
+ if (!nametab)
+ {
+ rc = mu_assoc_create (&nametab, 0);
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_assoc_create", NULL, rc);
+ return rc;
+ }
+ mu_assoc_set_destroy_item (nametab, mu_list_free_item);
+ }
+ rc = mu_assoc_install_ref2 (nametab, name, &refptr, refname);
+ switch (rc)
+ {
+ case 0:
+ ref = malloc (sizeof *ref);
+ if (!ref)
+ {
+ rc = errno;
+ mu_assoc_remove (nametab, name);
+ return rc;
+ }
+ *refptr = ref;
+ ref->count = 0;
+ break;
+
+ case MU_ERR_EXISTS:
+ ref = *refptr;
+ break;
+
+ default:
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_assoc_install_ref2", name, rc);
+ return rc;
+ }
+
+ ref->count++;
+ return 0;
+}
+
+int
+mu_ident_deref (char const *name)
+{
+ struct mu_ident_ref *ref;
+ int rc;
+
+ if (!name || !nametab)
+ return 0;
+
+ rc = mu_assoc_lookup (nametab, name, &ref);
+ switch (rc)
+ {
+ case 0:
+ if (--ref->count == 0)
+ mu_assoc_remove (nametab, name);
+ break;
+
+ case MU_ERR_NOENT:
+ break;
+
+ default:
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_assoc_lookup", name, rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+void
+mu_ident_stat (mu_stream_t str)
+{
+ size_t count, i;
+ mu_iterator_t itr;
+
+ mu_stream_printf (str, "BEGIN IDENT STAT\n");
+
+ mu_assoc_count (nametab, &count);
+ mu_stream_printf (str, "N=%zu\n", count);
+
+ if (count > 0)
+ {
+ int rc = mu_assoc_get_iterator (nametab, &itr);
+ if (rc)
+ mu_stream_printf (str, "mu_assoc_get_iterator: %s\n",
+ mu_strerror (rc));
+ else
+ {
+ i = 0;
+ for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
+ mu_iterator_next (itr), i)
+ {
+ const char *key;
+ struct mu_ident_ref *ref;
+
+ mu_iterator_current_kv (itr,
+ (const void **)&key, (void **)&ref);
+ mu_stream_printf (str, "%04zu: %s: %zu\n", i, key, ref->count);
+ }
+ }
+ mu_iterator_destroy (&itr);
+ }
+ mu_stream_printf (str, "END IDENT STAT\n");
+}
+
diff --git a/libmailutils/locus/linetrack.c b/libmailutils/locus/linetrack.c
new file mode 100644
index 0000000..86a3dd8
--- a/dev/null
+++ b/libmailutils/locus/linetrack.c
@@ -0,0 +1,268 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2017 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <mailutils/types.h>
+#include <mailutils/locus.h>
+#include <mailutils/error.h>
+
+/* The line-tracker structure keeps track of the last N lines read from a
+ text input file. For each line read it keeps the number of characters
+ in that line including the newline. This information is stored in a
+ syclic stack of N elements. Top of stack always represents the current
+ line. For the purpose of line tracker, current line is the line that is
+ being visited, such that its final newline character has not yet been
+ seen. Once the newline is seen, the line is pushed on stack, and a new
+ current line is assumed.
+
+ The value of N must not be less than 2.
+*/
+struct mu_linetrack
+{
+ char const *file_name; /* Name of the source file */
+ size_t max_lines; /* Max. number of lines history kept by tracker (N) */
+ size_t head; /* Index of the eldest element on stack */
+ size_t tos; /* Index of the most recent element on stack
+ (< max_lines) */
+ unsigned hline; /* Number of line corresponding to cols[head] */
+ unsigned *cols; /* Cyclic stack or character counts.
+ Number of characters in line (hline + n) is
+ cols[head + n] (0 <= n <= tos). */
+};
+
+static inline unsigned *
+cols_ptr (mu_linetrack_t trk, size_t n)
+{
+ return &trk->cols[(trk->head + n) % trk->max_lines];
+}
+
+static inline unsigned *
+cols_tos_ptr (mu_linetrack_t trk)
+{
+ return cols_ptr (trk, trk->tos);
+}
+
+static inline unsigned
+cols_peek (mu_linetrack_t trk, size_t n)
+{
+ return *cols_ptr (trk, n);
+}
+
+int
+mu_linetrack_create (mu_linetrack_t *ret,
+ char const *file_name, size_t max_lines)
+{
+ int rc;
+ struct mu_linetrack *trk;
+
+ trk = malloc (sizeof *trk);
+ if (!trk)
+ return errno;
+ trk->cols = calloc (max_lines, sizeof (trk->cols[0]));
+ if (!trk->cols)
+ {
+ rc = errno;
+ free (trk);
+ return rc;
+ }
+ rc = mu_ident_ref (file_name, &trk->file_name);
+ if (rc)
+ {
+ free (trk->cols);
+ free (trk);
+ return rc;
+ }
+
+ if (max_lines < 2)
+ max_lines = 2;
+ trk->max_lines = max_lines;
+ trk->head = 0;
+ trk->tos = 0;
+ trk->hline = 1;
+ trk->cols[0] = 0;
+
+ *ret = trk;
+ return 0;
+}
+
+int
+mu_linetrack_rebase (mu_linetrack_t trk, struct mu_locus_point const *pt)
+{
+ char const *file_name;
+ int rc = mu_ident_ref (pt->mu_file, &file_name);
+ if (rc)
+ return rc;
+ mu_ident_deref (trk->file_name);
+ trk->file_name = file_name;
+ trk->hline = pt->mu_line;
+ *cols_ptr (trk, 0) = pt->mu_col;
+ return 0;
+}
+
+void
+mu_linetrack_free (mu_linetrack_t trk)
+{
+ if (trk)
+ {
+ mu_ident_deref (trk->file_name);
+ free (trk->cols);
+ free (trk);
+ }
+}
+
+void
+mu_linetrack_destroy (mu_linetrack_t *trk)
+{
+ if (trk)
+ {
+ mu_linetrack_free (*trk);
+ *trk = NULL;
+ }
+}
+
+static inline unsigned *
+push (mu_linetrack_t trk)
+{
+ unsigned *ptr;
+ if (trk->tos == trk->max_lines - 1)
+ {
+ trk->head++;
+ trk->hline++;
+ }
+ else
+ trk->tos++;
+ *(ptr = cols_tos_ptr (trk)) = 0;
+ return ptr;
+}
+
+static inline unsigned *
+pop (mu_linetrack_t trk)
+{
+ if (trk->tos == 0)
+ return NULL;
+ trk->tos--;
+ return cols_tos_ptr (trk);
+}
+
+#ifndef SIZE_MAX
+# define SIZE_MAX (~((size_t)0))
+#endif
+
+int
+mu_linetrack_stat (struct mu_linetrack *trk, struct mu_linetrack_stat *st)
+{
+ size_t i, nch = 0;
+
+ for (i = 0; i <= trk->tos; 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->tos + 1;
+ st->n_chars = nch;
+
+ return 0;
+}
+
+int
+mu_linetrack_at_bol (struct mu_linetrack *trk)
+{
+ return *cols_tos_ptr (trk) == 0;
+}
+
+void
+mu_linetrack_advance (struct mu_linetrack *trk,
+ struct mu_locus_range *loc,
+ char const *text, size_t leng)
+{
+ unsigned *ptr;
+
+ if (text == NULL || leng == 0)
+ return;
+
+ mu_locus_point_set_file (&loc->beg, trk->file_name);
+ mu_locus_point_set_file (&loc->end, trk->file_name);
+ loc->beg.mu_line = trk->hline + trk->tos;
+ ptr = cols_tos_ptr (trk);
+ loc->beg.mu_col = *ptr + 1;
+ while (leng--)
+ {
+ (*ptr)++;
+ if (*text == '\n')
+ ptr = push (trk);
+ text++;
+ }
+ if (*ptr)
+ {
+ loc->end.mu_line = trk->hline + trk->tos;
+ loc->end.mu_col = *ptr;
+ }
+ else
+ {
+ /* Text ends with a newline. Keep the previous line number. */
+ loc->end.mu_line = trk->hline + trk->tos - 1;
+ loc->end.mu_col = cols_peek (trk, trk->tos - 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;
+ }
+ }
+}
+
+int
+mu_linetrack_locus (struct mu_linetrack *trk, struct mu_locus_point *lp)
+{
+ lp->mu_line = trk->hline + trk->tos;
+ return mu_locus_point_set_file (lp, trk->file_name);
+}
+
+int
+mu_linetrack_retreat (struct mu_linetrack *trk, size_t n)
+{
+ struct mu_linetrack_stat st;
+
+ mu_linetrack_stat (trk, &st);
+ if (n > st.n_chars)
+ return ERANGE;
+ else
+ {
+ unsigned *ptr = cols_tos_ptr (trk);
+ while (n--)
+ {
+ 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;
+ }
+ }
+ return 0;
+}
+
+
diff --git a/libmailutils/locus/locus.c b/libmailutils/locus/locus.c
new file mode 100644
index 0000000..cfa8080
--- a/dev/null
+++ b/libmailutils/locus/locus.c
@@ -0,0 +1,101 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2017 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <mailutils/types.h>
+#include <mailutils/locus.h>
+#include <mailutils/error.h>
+#include <mailutils/errno.h>
+
+int
+mu_locus_point_set_file (struct mu_locus_point *pt, const char *filename)
+{
+ int rc;
+ char const *ref;
+
+ rc = mu_ident_ref (filename, &ref);
+ if (rc)
+ return rc;
+ mu_ident_deref (pt->mu_file);
+ pt->mu_file = ref;
+ return 0;
+}
+
+void
+mu_locus_point_init (struct mu_locus_point *pt)
+{
+ memset (pt, 0, sizeof *pt);
+}
+
+void
+mu_locus_point_deinit (struct mu_locus_point *pt)
+{
+ mu_ident_deref (pt->mu_file);
+ memset (pt, 0, sizeof *pt);
+}
+
+int
+mu_locus_point_copy (struct mu_locus_point *dest,
+ struct mu_locus_point const *src)
+{
+ int rc = mu_locus_point_set_file (dest, src->mu_file);
+ if (rc == 0)
+ {
+ dest->mu_col = src->mu_col;
+ dest->mu_line = src->mu_line;
+ }
+ return rc;
+}
+
+void
+mu_locus_range_init (struct mu_locus_range *dest)
+{
+ memset (dest, 0, sizeof *dest);
+}
+
+int
+mu_locus_range_copy (struct mu_locus_range *dest,
+ struct mu_locus_range const *src)
+{
+ int rc;
+ struct mu_locus_range tmp = MU_LOCUS_RANGE_INITIALIZER;
+
+ if (!dest)
+ return MU_ERR_OUT_PTR_NULL;
+
+ rc = mu_locus_point_copy (&tmp.beg, &src->beg);
+ if (rc == 0)
+ {
+ rc = mu_locus_point_copy (&tmp.end, &src->end);
+ if (rc)
+ mu_locus_point_deinit (&tmp.beg);
+ else
+ {
+ mu_locus_range_deinit (dest);
+ *dest = tmp;
+ }
+ }
+ return rc;
+}
+
+void
+mu_locus_range_deinit (struct mu_locus_range *lr)
+{
+ mu_locus_point_deinit (&lr->beg);
+ mu_locus_point_deinit (&lr->end);
+}
diff --git a/libmailutils/locus/strprloc.c b/libmailutils/locus/strprloc.c
new file mode 100644
index 0000000..4f074a7
--- a/dev/null
+++ b/libmailutils/locus/strprloc.c
@@ -0,0 +1,10 @@
+#include <mailutils/types.h>
+#include <mailutils/locus.h>
+#include <mailutils/stream.h>
+
+#define STREAM_TYPE mu_stream_t
+#define STREAM_PRINTF mu_stream_printf
+#define PRINT_LOCUS_POINT mu_stream_print_locus_point
+#define PRINT_LOCUS_RANGE mu_stream_print_locus_range
+#include "genprloc.c"
+
diff --git a/libmailutils/stream/logstream.c b/libmailutils/stream/logstream.c
index 5bca3c2..1cc2b4b 100644
--- a/libmailutils/stream/logstream.c
+++ b/libmailutils/stream/logstream.c
@@ -30,6 +30,7 @@
#include <mailutils/nls.h>
#include <mailutils/stream.h>
#include <mailutils/debug.h>
+#include <mailutils/locus.h>
#include <mailutils/sys/logstream.h>
char *_mu_severity_str[] = {
@@ -69,25 +70,77 @@ mu_severity_to_string (unsigned n, const char **pstr)
return 0;
}
+static void
+lr_set_line (struct mu_locus_range *loc, unsigned val, int end)
+{
+ if (end)
+ loc->end.mu_line = val;
+ else
+ loc->beg.mu_line = val;
+}
+
+static void
+lr_set_col (struct mu_locus_range *loc, unsigned val, int end)
+{
+ if (end)
+ loc->end.mu_col = val;
+ else
+ loc->beg.mu_col = val;
+}
+
static int
-_locus_set_file (struct mu_locus *loc, const char *file, size_t len)
+lr_set_file (struct mu_locus_range *loc, char const *fname, unsigned len,
+ int end)
{
- free (loc->mu_file);
- if (file)
+ char const *refname;
+ struct mu_locus_point *pt = end ? &loc->end : &loc->beg;
+ int rc;
+
+ if (fname == NULL)
{
- loc->mu_file = malloc (len + 1);
- if (!loc->mu_file)
- return ENOMEM;
- memcpy (loc->mu_file, file, len);
- loc->mu_file[len] = 0;
+ refname = NULL;
+ rc = 0;
}
+ else if (len == 0)
+ rc = mu_ident_ref (fname, &refname);
else
- loc->mu_file = NULL;
+ {
+ char *name;
+
+ name = malloc (len + 1);
+ if (!name)
+ return errno;
+ memcpy (name, fname, len);
+ name[len] = 0;
+ rc = mu_ident_ref (name, &refname);
+ free (name);
+ }
+ if (rc)
+ return rc;
+ mu_ident_deref (pt->mu_file);
+ pt->mu_file = refname;
return 0;
}
-#define _locus_set_line(loc, line) ((loc)->mu_line = line)
-#define _locus_set_col(loc, col) ((loc)->mu_col = col)
+/* Field modification map (binary):
+
+ FfLlCc
+
+ The bits f, l, and c (file, line, and column) are toggled cyclically.
+ The value 0 means locus beg, 1 meand locus end.
+ The bits F, L, and C are set once and indicate that the corresponding
+ bit was toggled at least once.
+ */
+#define FMM_COL 0
+#define FMM_LINE 1
+#define FMM_FILE 2
+
+#define FMM_SHIFT(n) ((n)<<1)
+#define FMM_MASK(n) (0x3 << FMM_SHIFT (n))
+#define FMM_VAL(m,n) (((m) >> FMM_SHIFT (n)) & 0x1)
+#define FMM_SET(m,n,v) ((m) = ((m) & ~FMM_MASK (n)) | (((v) << FMM_SHIFT (n))|0x2))
+#define FMM_CYCLE(m, n) \
+ FMM_SET ((m), (n), ((FMM_VAL ((m), (n)) + 1) % 2))
static int
_log_write (struct _mu_stream *str, const char *buf, size_t size,
@@ -96,8 +149,8 @@ _log_write (struct _mu_stream *str, const char *buf, size_t size,
struct _mu_log_stream *sp = (struct _mu_log_stream *)str;
unsigned severity = sp->severity;
int logmode = sp->logmode;
- struct mu_locus loc = sp->locus;
- const char *fname = NULL;
+ struct mu_locus_range loc;
+ int fmm = 0;
unsigned flen = 0;
int save_locus = 0;
int rc;
@@ -120,6 +173,10 @@ _log_write (struct _mu_stream *str, const char *buf, size_t size,
n = __x; \
} while (0)
+ loc = sp->locrange;
+ mu_ident_ref (loc.beg.mu_file, &loc.beg.mu_file);
+ mu_ident_ref (loc.end.mu_file, &loc.end.mu_file);
+
/* Tell them we've consumed everything */
*pnwrite = size;
@@ -167,21 +224,24 @@ _log_write (struct _mu_stream *str, const char *buf, size_t size,
case 'l':
/* Input line (decimal) */
READNUM (n);
- _locus_set_line (&loc, n);
+ lr_set_line (&loc, n, FMM_VAL (fmm, FMM_LINE));
+ FMM_CYCLE (fmm, FMM_LINE);
logmode |= MU_LOGMODE_LOCUS;
break;
case 'c':
/* Column in input line (decimal) */
READNUM (n);
- _locus_set_col (&loc, n);
+ lr_set_col (&loc, n, FMM_VAL (fmm, FMM_COL));
+ FMM_CYCLE (fmm, FMM_COL);
logmode |= MU_LOGMODE_LOCUS;
break;
case 'f':
/* File name. Format: <N>S */
READNUM (flen);
- fname = buf;
+ lr_set_file (&loc, buf, flen, FMM_VAL (fmm, FMM_FILE));
+ FMM_CYCLE (fmm, FMM_FILE);
buf += flen;
size -= flen;
logmode |= MU_LOGMODE_LOCUS;
@@ -197,58 +257,37 @@ _log_write (struct _mu_stream *str, const char *buf, size_t size,
if (severity >= _mu_severity_num)
severity = MU_LOG_EMERG;
- if (fname)
- {
- loc.mu_file = NULL;
- _locus_set_file (&loc, fname, flen);
- }
-
if (save_locus)
- {
- _locus_set_file (&sp->locus, loc.mu_file, strlen (loc.mu_file));
- _locus_set_line (&sp->locus, loc.mu_line);
- _locus_set_col (&sp->locus, loc.mu_col);
- }
+ mu_locus_range_copy (&sp->locrange, &loc);
if (severity < sp->threshold)
+ rc = 0;
+ else
{
- if (fname)
- free (loc.mu_file);
- return 0;
- }
-
- mu_stream_ioctl (sp->transport, MU_IOCTL_LOGSTREAM,
- MU_IOCTL_LOGSTREAM_SET_SEVERITY, &severity);
+ mu_stream_ioctl (sp->transport, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_SEVERITY, &severity);
- if (logmode & MU_LOGMODE_LOCUS)
- {
- if (loc.mu_file)
+ if ((logmode & MU_LOGMODE_LOCUS) && loc.beg.mu_file)
+ {
+ mu_stream_print_locus_range (sp->transport, &loc);
+ mu_stream_write (sp->transport, ": ", 2, NULL);
+ }
+
+ if ((logmode & MU_LOGMODE_SEVERITY) &&
+ !(sp->sevmask & MU_DEBUG_LEVEL_MASK (severity)))
{
- mu_stream_write (sp->transport, loc.mu_file,
- strlen (loc.mu_file), NULL);
- mu_stream_write (sp->transport, ":", 1, NULL);
- if (loc.mu_line)
- mu_stream_printf (sp->transport, "%u", loc.mu_line);
- mu_stream_write (sp->transport, ":", 1, NULL);
- if (loc.mu_col)
- mu_stream_printf (sp->transport, "%u:", loc.mu_col);
- mu_stream_write (sp->transport, " ", 1, NULL);
+ char *s = gettext (_mu_severity_str[severity]);
+ rc = mu_stream_write (sp->transport, s, strlen (s), NULL);
+ if (rc)
+ return rc;
+ mu_stream_write (sp->transport, ": ", 2, NULL);
}
+ rc = mu_stream_write (sp->transport, buf, size, NULL);
}
-
- if (fname)
- free (loc.mu_file);
- if ((logmode & MU_LOGMODE_SEVERITY) &&
- !(sp->sevmask & MU_DEBUG_LEVEL_MASK(severity)))
- {
- char *s = gettext (_mu_severity_str[severity]);
- rc = mu_stream_write (sp->transport, s, strlen (s), NULL);
- if (rc)
- return rc;
- mu_stream_write (sp->transport, ": ", 2, NULL);
- }
- return mu_stream_write (sp->transport, buf, size, NULL);
+ mu_ident_deref (loc.beg.mu_file);
+ mu_ident_deref (loc.end.mu_file);
+ return rc;
}
static int
@@ -262,6 +301,7 @@ static void
_log_done (struct _mu_stream *str)
{
struct _mu_log_stream *sp = (struct _mu_log_stream *)str;
+ mu_locus_range_deinit (&sp->locrange);
mu_stream_destroy (&sp->transport);
}
@@ -375,72 +415,133 @@ _log_ctl (struct _mu_stream *str, int code, int opcode, void *arg)
sp->logmode = *(int*)arg;
break;
- case MU_IOCTL_LOGSTREAM_GET_LOCUS:
+ case MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE:
+ {
+ struct mu_locus_range *lr = arg;
+ if (!arg)
+ {
+ mu_ident_deref (sp->locrange.beg.mu_file);
+ mu_ident_deref (sp->locrange.end.mu_file);
+ memset (&sp->locrange, 0, sizeof sp->locrange);
+ }
+ else
+ {
+ char const *begname, *endname;
+
+ status = mu_ident_ref (lr->beg.mu_file, &begname);
+ if (status)
+ return status;
+ status = mu_ident_ref (lr->end.mu_file, &endname);
+ if (status)
+ {
+ mu_ident_deref (begname);
+ return status;
+ }
+ mu_ident_deref (sp->locrange.beg.mu_file);
+ sp->locrange.beg.mu_file = begname;
+ sp->locrange.beg.mu_line = lr->beg.mu_line;
+ sp->locrange.beg.mu_col = lr->beg.mu_col;
+
+ mu_ident_deref (sp->locrange.end.mu_file);
+ sp->locrange.end.mu_file = endname;
+ sp->locrange.end.mu_line = lr->end.mu_line;
+ sp->locrange.end.mu_col = lr->end.mu_col;
+ }
+ }
+ break;
+
+ case MU_IOCTL_LOGSTREAM_GET_LOCUS_RANGE:
+ if (!arg)
+ return EINVAL;
+ else
+ {
+ struct mu_locus_range *lr = arg;
+ char const *begname, *endname;
+
+ status = mu_ident_ref (sp->locrange.beg.mu_file, &begname);
+ if (status)
+ return status;
+ status = mu_ident_ref (sp->locrange.end.mu_file, &endname);
+ if (status)
+ {
+ mu_ident_deref (begname);
+ return status;
+ }
+ lr->beg.mu_file = begname;
+ lr->beg.mu_line = sp->locrange.beg.mu_line;
+ lr->beg.mu_col = sp->locrange.beg.mu_col;
+ lr->end.mu_file = endname;
+ lr->end.mu_line = sp->locrange.end.mu_line;
+ lr->end.mu_col = sp->locrange.end.mu_col;
+ }
+ break;
+
+ case MU_IOCTL_LOGSTREAM_GET_LOCUS_DEPRECATED:
if (!arg)
return EINVAL;
else
{
- struct mu_locus *ploc = arg;
- if (sp->locus.mu_file)
+ struct mu_locus_DEPRECATED *ploc = arg;
+ if (sp->locrange.beg.mu_file)
{
- ploc->mu_file = strdup (sp->locus.mu_file);
+ ploc->mu_file = strdup (sp->locrange.beg.mu_file);
if (!ploc->mu_file)
return ENOMEM;
}
else
ploc->mu_file = NULL;
- ploc->mu_line = sp->locus.mu_line;
- ploc->mu_col = sp->locus.mu_col;
+ ploc->mu_line = sp->locrange.beg.mu_line;
+ ploc->mu_col = sp->locrange.beg.mu_col;
}
break;
- case MU_IOCTL_LOGSTREAM_SET_LOCUS:
+ case MU_IOCTL_LOGSTREAM_SET_LOCUS_DEPRECATED:
{
- struct mu_locus *ploc = arg;
- if (!arg)
+ struct mu_locus_DEPRECATED *ploc = arg;
+
+ mu_ident_deref (sp->locrange.end.mu_file);
+ sp->locrange.end.mu_file = NULL;
+ if (arg)
{
- free (sp->locus.mu_file);
- sp->locus.mu_file = NULL;
- sp->locus.mu_line = 0;
- sp->locus.mu_col = 0;
+ status = lr_set_file (&sp->locrange, ploc->mu_file, 0, 0);
+ if (status)
+ return status;
+ lr_set_line (&sp->locrange, ploc->mu_line, 0);
+ lr_set_col (&sp->locrange, ploc->mu_col, 0);
}
else
{
- if (ploc->mu_file)
- _locus_set_file (&sp->locus, ploc->mu_file,
- strlen (ploc->mu_file));
- if (ploc->mu_line)
- _locus_set_line (&sp->locus, ploc->mu_line);
- if (ploc->mu_col)
- _locus_set_col (&sp->locus, ploc->mu_col);
+ mu_ident_deref (sp->locrange.beg.mu_file);
+ sp->locrange.beg.mu_file = NULL;
}
+
break;
}
case MU_IOCTL_LOGSTREAM_SET_LOCUS_LINE:
if (!arg)
return EINVAL;
- sp->locus.mu_line = *(unsigned*)arg;
+ sp->locrange.beg.mu_line = *(unsigned*)arg;
break;
case MU_IOCTL_LOGSTREAM_SET_LOCUS_COL:
if (!arg)
return EINVAL;
- sp->locus.mu_col = *(unsigned*)arg;
+ sp->locrange.beg.mu_col = *(unsigned*)arg;
break;
case MU_IOCTL_LOGSTREAM_ADVANCE_LOCUS_LINE:
if (!arg)
- sp->locus.mu_line++;
+ sp->locrange.beg.mu_line++;
else
- sp->locus.mu_line += *(int*)arg;
+ sp->locrange.beg.mu_line += *(int*)arg;
break;
case MU_IOCTL_LOGSTREAM_ADVANCE_LOCUS_COL:
if (!arg)
- sp->locus.mu_col++;
+ sp->locrange.beg.mu_col++;
else
- sp->locus.mu_col += *(int*)arg;
+ sp->locrange.beg.mu_col += *(int*)arg;
break;
case MU_IOCTL_LOGSTREAM_SUPPRESS_SEVERITY:
@@ -484,14 +585,12 @@ _log_ctl (struct _mu_stream *str, int code, int opcode, void *arg)
newp->threshold = sp->threshold;
newp->logmode = sp->logmode;
newp->sevmask = sp->sevmask;
- if (sp->locus.mu_file)
- {
- newp->locus.mu_file = strdup (sp->locus.mu_file);
- if (!newp->locus.mu_file)
- return ENOMEM;
- }
- newp->locus.mu_line = sp->locus.mu_line;
- newp->locus.mu_col = sp->locus.mu_col;
+ newp->locrange = sp->locrange;
+ mu_ident_ref (sp->locrange.beg.mu_file,
+ &sp->locrange.beg.mu_file);
+ mu_ident_ref (sp->locrange.end.mu_file,
+ &sp->locrange.end.mu_file);
+
*(mu_stream_t*) arg = str;
}
break;
@@ -545,5 +644,33 @@ mu_log_stream_create (mu_stream_t *pstr, mu_stream_t transport)
return 0;
}
+
+static char wiki_url[] = "http://mailutils.org/wiki/Source_location_API#Deprecated_interface";
+
+int
+mu_ioctl_logstream_get_locus_deprecated (void)
+{
+ static int warned;
+ if (!warned)
+ {
+ mu_error (_("the program uses MU_IOCTL_LOGSTREAM_GET_LOCUS, which is deprecated"));
+ mu_error (_("please see %s, for detailed guidelines"), wiki_url);
+ warned = 1;
+ }
+ return MU_IOCTL_LOGSTREAM_GET_LOCUS_DEPRECATED;
+}
+
+int
+mu_ioctl_logstream_set_locus_deprecated (void)
+{
+ static int warned;
+ if (!warned)
+ {
+ mu_error (_("program uses MU_IOCTL_LOGSTREAM_SET_LOCUS, which is deprecated"));
+ mu_error (_("please see %s, for detailed guidelines"), wiki_url);
+ warned = 1;
+ }
+ return MU_IOCTL_LOGSTREAM_SET_LOCUS_DEPRECATED;
+}
diff --git a/libmailutils/tests/.gitignore b/libmailutils/tests/.gitignore
index 39018d5..f0c34b9 100644
--- a/libmailutils/tests/.gitignore
+++ b/libmailutils/tests/.gitignore
@@ -19,6 +19,8 @@ fsfolder
globtest
imapio
listop
+linetrack
+logstr
mailcap
mimehdr
modmesg
diff --git a/libmailutils/tests/Makefile.am b/libmailutils/tests/Makefile.am
index f4f7fe2..e870cd7 100644
--- a/libmailutils/tests/Makefile.am
+++ b/libmailutils/tests/Makefile.am
@@ -54,6 +54,8 @@ noinst_PROGRAMS = \
globtest\
imapio\
listop\
+ linetrack\
+ logstr\
mailcap\
mimehdr\
modtofsaf\
@@ -105,6 +107,8 @@ TESTSUITE_AT = \
inline-comment.at\
linecon.at\
list.at\
+ linetrack.at\
+ logstr.at\
mailcap.at\
mimehdr.at\
modmesg00.at\
diff --git a/libmailutils/tests/linetrack.at b/libmailutils/tests/linetrack.at
new file mode 100644
index 0000000..6f01b4d
--- a/dev/null
+++ b/libmailutils/tests/linetrack.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([Line tracker])
+
+m4_pushdef([TRACKTEST],[
+AT_SETUP([$1])
+AT_KEYWORDS([tracker $2])
+AT_CHECK([linetrack 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
+],
+[linetrack: retreat count too big
+])
+
+m4_popdef([TRACKTEST])
diff --git a/libmailutils/tests/linetrack.c b/libmailutils/tests/linetrack.c
new file mode 100644
index 0000000..c99440e
--- a/dev/null
+++ b/libmailutils/tests/linetrack.c
@@ -0,0 +1,66 @@
+#include <mailutils/mailutils.h>
+#include <mailutils/locus.h>
+
+int
+main (int argc, char **argv)
+{
+ unsigned long max_lines;
+ char *end;
+ mu_linetrack_t trk;
+ int rc;
+ char *buf = NULL;
+ size_t size, n;
+
+ mu_set_program_name (argv[0]);
+ mu_stdstream_setup (MU_STDSTREAM_RESET_NONE);
+
+ if (argc != 3)
+ {
+ mu_error ("usage: %s FILE LINES", mu_program_name);
+ return 1;
+ }
+ max_lines = strtoul (argv[2], &end, 10);
+ if (*end || max_lines == 0)
+ {
+ mu_error ("invalid number of lines");
+ return 1;
+ }
+
+ MU_ASSERT (mu_linetrack_create (&trk, argv[1], max_lines));
+ while ((rc = mu_stream_getline (mu_strin, &buf, &size, &n)) == 0 && n > 0)
+ {
+ struct mu_locus_range lr = MU_LOCUS_RANGE_INITIALIZER;
+ char *tok;
+
+ n = mu_rtrim_class (buf, MU_CTYPE_SPACE);
+ if (n == 0)
+ continue;
+ if (buf[0] == '\\' && buf[1] == '-')
+ {
+ long x = strtol (buf+2, &end, 10);
+ if (*end || x == 0)
+ {
+ mu_error ("bad number");
+ continue;
+ }
+ rc = mu_linetrack_retreat (trk, x);
+ if (rc == ERANGE)
+ mu_error ("retreat count too big");
+ else if (rc)
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_linetrack_retreat", buf+2,
+ rc);
+ }
+ else
+ {
+ mu_c_str_unescape (buf, "\\\n", "\\n", &tok);
+ mu_linetrack_advance (trk, &lr, tok, strlen (tok));
+ free (tok);
+ mu_stream_lprintf (mu_strout, &lr, "%s\n", buf);
+ }
+ mu_locus_range_deinit (&lr);
+ }
+ mu_linetrack_destroy (&trk);
+ return 0;
+}
+
+
diff --git a/libmailutils/tests/logstr.at b/libmailutils/tests/logstr.at
new file mode 100644
index 0000000..8a97dea
--- a/dev/null
+++ b/libmailutils/tests/logstr.at
@@ -0,0 +1,77 @@
+# 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_SETUP(Logger stream)
+AT_KEYWORDS([logstream])
+AT_CHECK([logstr],
+[0],
+[00. simple print
+hello world
+01. severity
+info: one
+emerg: two
+mode was: 0x0001
+02. suppress severity
+info: this message is seen
+emerg: and this one as well
+03. suppress severity name
+info: this message is seen
+emerg: and this one as well
+04. severity mask
+one
+two
+emerg: three
+05. locus: file, line
+input:1: file, line
+06. locus: file, line, col
+input:1.1-10: file, line, col
+07. locus: file, line-range
+input:1-2: file, line-range
+08. locus: file, line-range, col
+input:1.1-2.10: file, line-range, col
+09. locus: file-range, line-range, col-range
+input:1.1-next:2.10: file-range, line-range, col-range
+10. set locus line
+input:1.1-next:2.10: initial
+input:8.1-next:2.10: locus line changed
+11. advance locus line
+input:1.1-next:5.10: initial
+input:3.1-next:5.10: locus line advanced
+12. set locus column
+input:1.1-next:2.10: initial
+input:1.8-next:2.10: locus column changed
+13. advance locus column
+input:1.1-next:5.10: initial
+input:1.5-next:5.10: locus line advanced
+14. fmt: severity
+info: severity
+15. fmt: locus (file, line)
+a:10: one
+16. fmt: locus (file, line, column)
+a:10.5: one
+17. fmt: locus (range)
+a:10.5-b:14.8: one
+18. fmt: locus; restore defaults
+a:10.5-b:14.8: one
+default
+19. fmt: locus; restore defaults, display locus
+a:10.5-b:14.8: one
+input:1.1-next:5.10: default
+20. fmt: set locus
+a:10.5-b:14.8: one
+a:10.5-b:14.8: default
+])
+AT_CLEANUP \ No newline at end of file
diff --git a/libmailutils/tests/logstr.c b/libmailutils/tests/logstr.c
new file mode 100644
index 0000000..bf65e21
--- a/dev/null
+++ b/libmailutils/tests/logstr.c
@@ -0,0 +1,729 @@
+/* This file is part of GNU Mailutils test suite
+ 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/>. */
+
+#include <mailutils/mailutils.h>
+#include <mailutils/locus.h>
+
+/* Check normal operation.
+ Expected output: hello world
+*/
+static void
+simple_print (mu_stream_t str)
+{
+ mu_stream_printf (str, "hello world\n");
+}
+
+/* Check severity control.
+ Expected output:
+ info: one
+ emerg: two
+ mode was: 0x0001
+*/
+static void
+check_severity (mu_stream_t str)
+{
+ unsigned severity = MU_DIAG_INFO;
+ int mode = MU_LOGMODE_SEVERITY, old_mode;
+
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
+
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_SEVERITY, &severity);
+ mu_stream_printf (str, "one\n");
+
+ severity = MU_DIAG_EMERG;
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_SEVERITY, &severity);
+ mu_stream_printf (str, "two\n");
+
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_GET_MODE, &old_mode);
+
+ mode = 0;
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
+ mu_stream_printf (str, "mode was: 0x%04X\n", old_mode);
+}
+
+/* Check severity suppression mechanism.
+ Expected output:
+ info: this message is seen
+ emerg: and this one as well
+*/
+static void
+check_suppress (mu_stream_t str)
+{
+ unsigned severity;
+ int mode = MU_LOGMODE_SEVERITY;
+
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
+
+ severity = MU_DIAG_INFO;
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SUPPRESS_SEVERITY,
+ &severity);
+
+ severity = MU_DIAG_DEBUG;
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_SEVERITY, &severity);
+
+ mu_stream_printf (str, "this message is not seen\n");
+
+ severity = MU_DIAG_INFO;
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_SEVERITY, &severity);
+ mu_stream_printf (str, "this message is seen\n");
+
+ severity = MU_DIAG_EMERG;
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_SEVERITY, &severity);
+ mu_stream_printf (str, "and this one as well\n");
+}
+
+/* Check suppression by severity name.
+ Expected output:
+ info: this message is seen
+ emerg: and this one as well
+*/
+static void
+check_suppress_name (mu_stream_t str)
+{
+ int mode = MU_LOGMODE_SEVERITY, severity;
+
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
+
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SUPPRESS_SEVERITY_NAME,
+ "info");
+
+ severity = MU_DIAG_DEBUG;
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_SEVERITY, &severity);
+
+ mu_stream_printf (str, "this message is not seen\n");
+
+ severity = MU_DIAG_INFO;
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_SEVERITY, &severity);
+ mu_stream_printf (str, "this message is seen\n");
+
+ severity = MU_DIAG_EMERG;
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_SEVERITY, &severity);
+ mu_stream_printf (str, "and this one as well\n");
+}
+
+static void
+comp_range (mu_stream_t str, struct mu_locus_range *lr1,
+ char const *file, int line)
+{
+ struct mu_locus_range lr2;
+
+ MU_ASSERT (mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_GET_LOCUS_RANGE, &lr2));
+ if (strcmp (lr1->beg.mu_file, lr2.beg.mu_file))
+ mu_error ("%s:%d: beg.mu_file differs", file, line);
+ if (lr1->beg.mu_line != lr2.beg.mu_line)
+ mu_error ("%s:%d: beg.mu_line differs", file, line);
+ if (lr1->beg.mu_col != lr2.beg.mu_col)
+ mu_error ("%s:%d: beg.mu_col differs", file, line);
+ mu_ident_deref (lr2.beg.mu_file);
+
+ if (strcmp (lr1->end.mu_file, lr2.end.mu_file))
+ mu_error ("%s:%d: end.mu_file differs", __FILE__, __LINE__);
+ if (lr1->end.mu_line != lr2.end.mu_line)
+ mu_error ("%s:%d: end.mu_line differs", __FILE__, __LINE__);
+ if (lr1->end.mu_col != lr2.end.mu_col)
+ mu_error ("%s:%d: end.mu_col differs", __FILE__, __LINE__);
+
+ mu_ident_deref (lr2.end.mu_file);
+}
+
+/* Check MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE.
+ Passed: file, line.
+ Expected output:
+ input:1: file, line
+*/
+static void
+lr_file_line (mu_stream_t str)
+{
+ int mode = MU_LOGMODE_LOCUS;
+ struct mu_locus_range lr;
+
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
+
+ lr.beg.mu_file = "input";
+ lr.beg.mu_line = 1;
+ lr.beg.mu_col = 0;
+
+ lr.end.mu_file = "input";
+ lr.end.mu_line = 1;
+ lr.end.mu_col = 0;
+
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &lr);
+
+ mu_stream_printf (str, "file, line\n");
+
+ comp_range (str, &lr, __FILE__, __LINE__);
+}
+
+/* Check MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE.
+ Passed: file, line, col.
+ Expected output:
+ input:1.1-10: file, line, col
+*/
+static void
+lr_file_line_col (mu_stream_t str)
+{
+ int mode = MU_LOGMODE_LOCUS;
+ struct mu_locus_range lr;
+
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
+
+ lr.beg.mu_file = "input";
+ lr.beg.mu_line = 1;
+ lr.beg.mu_col = 1;
+
+ lr.end.mu_file = "input";
+ lr.end.mu_line = 1;
+ lr.end.mu_col = 10;
+
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &lr);
+
+ mu_stream_printf (str, "file, line, col\n");
+
+ comp_range (str, &lr, __FILE__, __LINE__);
+}
+
+/* Check MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE.
+ Passed: file, line-range
+ Expected output:
+ input:1-2: file, line-range
+*/
+static void
+lr_file_line2 (mu_stream_t str)
+{
+ int mode = MU_LOGMODE_LOCUS;
+ struct mu_locus_range lr;
+
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
+
+ lr.beg.mu_file = "input";
+ lr.beg.mu_line = 1;
+ lr.beg.mu_col = 0;
+
+ lr.end.mu_file = "input";
+ lr.end.mu_line = 2;
+ lr.end.mu_col = 0;
+
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &lr);
+
+ mu_stream_printf (str, "file, line-range\n");
+
+ comp_range (str, &lr, __FILE__, __LINE__);
+}
+
+/* Check MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE.
+ Passed: file, line-range, column
+ Expected output:
+ input:1.1-2.10: file, line-range, col
+*/
+static void
+lr_file_line2_col (mu_stream_t str)
+{
+ int mode = MU_LOGMODE_LOCUS;
+ struct mu_locus_range lr;
+
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
+
+ lr.beg.mu_file = "input";
+ lr.beg.mu_line = 1;
+ lr.beg.mu_col = 1;
+
+ lr.end.mu_file = "input";
+ lr.end.mu_line = 2;
+ lr.end.mu_col = 10;
+
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &lr);
+
+ mu_stream_printf (str, "file, line-range, col\n");
+
+ comp_range (str, &lr, __FILE__, __LINE__);
+}
+
+/* Check MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE.
+ Passed: file-range, line-range, column-range
+ Expected output:
+ input:1.1-next:2.10: file-range, line-range, col-range
+*/
+static void
+lr_file2_line_col (mu_stream_t str)
+{
+ int mode = MU_LOGMODE_LOCUS;
+ struct mu_locus_range lr;
+
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
+
+ lr.beg.mu_file = "input";
+ lr.beg.mu_line = 1;
+ lr.beg.mu_col = 1;
+
+ lr.end.mu_file = "next";
+ lr.end.mu_line = 2;
+ lr.end.mu_col = 10;
+
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &lr);
+
+ mu_stream_printf (str, "file-range, line-range, col-range\n");
+
+ comp_range (str, &lr, __FILE__, __LINE__);
+}
+
+/* Check MU_IOCTL_LOGSTREAM_SET_LOCUS_LINE.
+ Expected output:
+ input:1.1-next:2.10: initial
+ input:8.1-next:2.10: locus line changed
+*/
+static void
+set_locus_line (mu_stream_t str)
+{
+ int mode = MU_LOGMODE_LOCUS;
+ struct mu_locus_range lr;
+ unsigned line;
+
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
+
+ lr.beg.mu_file = "input";
+ lr.beg.mu_line = 1;
+ lr.beg.mu_col = 1;
+
+ lr.end.mu_file = "next";
+ lr.end.mu_line = 2;
+ lr.end.mu_col = 10;
+
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &lr);
+ mu_stream_printf (str, "initial\n");
+ line = 8;
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_LINE, &line);
+ mu_stream_printf (str, "locus line changed\n");
+ lr.beg.mu_line = line;
+ comp_range (str, &lr, __FILE__, __LINE__);
+}
+
+/* Check MU_IOCTL_LOGSTREAM_ADVANCE_LOCUS_LINE.
+ Expected output:
+ input:1.1-next:5.10: initial
+ input:3.1-next:5.10: locus line advanced
+*/
+static void
+advance_locus_line (mu_stream_t str)
+{
+ int mode = MU_LOGMODE_LOCUS;
+ struct mu_locus_range lr;
+ unsigned line;
+
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
+
+ lr.beg.mu_file = "input";
+ lr.beg.mu_line = 1;
+ lr.beg.mu_col = 1;
+
+ lr.end.mu_file = "next";
+ lr.end.mu_line = 5;
+ lr.end.mu_col = 10;
+
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &lr);
+ mu_stream_printf (str, "initial\n");
+ line = 2;
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_ADVANCE_LOCUS_LINE, &line);
+ mu_stream_printf (str, "locus line advanced\n");
+
+ lr.beg.mu_line += line;
+ comp_range (str, &lr, __FILE__, __LINE__);
+}
+
+/* Check MU_IOCTL_LOGSTREAM_SET_LOCUS_COL.
+ Expected output:
+ input:1.1-next:2.10: initial
+ input:1.8-next:2.10: locus column changed
+*/
+static void
+set_locus_col (mu_stream_t str)
+{
+ int mode = MU_LOGMODE_LOCUS;
+ struct mu_locus_range lr;
+ unsigned col;
+
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
+
+ lr.beg.mu_file = "input";
+ lr.beg.mu_line = 1;
+ lr.beg.mu_col = 1;
+
+ lr.end.mu_file = "next";
+ lr.end.mu_line = 2;
+ lr.end.mu_col = 10;
+
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &lr);
+ mu_stream_printf (str, "initial\n");
+ col = 8;
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_COL, &col);
+ mu_stream_printf (str, "locus column changed\n");
+ lr.beg.mu_col = col;
+ comp_range (str, &lr, __FILE__, __LINE__);
+}
+
+/* Check MU_IOCTL_LOGSTREAM_ADVANCE_LOCUS_COL.
+ Expected output:
+ input:1.1-next:5.10: initial
+ input:1.5-next:5.10: locus line advanced
+*/
+static void
+advance_locus_col (mu_stream_t str)
+{
+ int mode = MU_LOGMODE_LOCUS;
+ struct mu_locus_range lr;
+ unsigned col;
+
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
+
+ lr.beg.mu_file = "input";
+ lr.beg.mu_line = 1;
+ lr.beg.mu_col = 1;
+
+ lr.end.mu_file = "next";
+ lr.end.mu_line = 5;
+ lr.end.mu_col = 10;
+
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &lr);
+ mu_stream_printf (str, "initial\n");
+ col = 4;
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_ADVANCE_LOCUS_COL, &col);
+ mu_stream_printf (str, "locus line advanced\n");
+
+ lr.beg.mu_col += col;
+ comp_range (str, &lr, __FILE__, __LINE__);
+}
+
+/* Check severity mask.
+ Expected output:
+ one
+ two
+ emerg: two
+ */
+static void
+check_severity_mask (mu_stream_t str)
+{
+ unsigned severity;
+ int mode = MU_LOGMODE_SEVERITY, mask;
+
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
+
+ mask = MU_DEBUG_LEVEL_UPTO (MU_DIAG_NOTICE);
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_SEVERITY_MASK, &mask);
+
+ severity = MU_DIAG_INFO;
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_SEVERITY, &severity);
+ mu_stream_printf (str, "one\n");
+
+ severity = MU_DIAG_NOTICE;
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_SEVERITY, &severity);
+ mu_stream_printf (str, "two\n");
+
+ severity = MU_DIAG_EMERG;
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_SEVERITY, &severity);
+ mu_stream_printf (str, "three\n");
+}
+
+/* Check ESC-s & ESC-O format specifiers.
+ Expected output:
+ info: severity
+*/
+static void
+fmt_severity (mu_stream_t str)
+{
+ mu_stream_printf (str, "\033s<%d>\033O<%d>severity\n",
+ MU_DIAG_INFO, MU_LOGMODE_SEVERITY);
+}
+
+/* Check ESC-f and ESC-l format specifiers.
+ Expected output:
+ a:10: one
+*/
+static void
+fmt_locus1 (mu_stream_t str)
+{
+ char *file = "a";
+ mu_stream_printf (str, "\033f<%d>%s\033l<%d>one\n",
+ (int) strlen (file), file, 10);
+}
+
+/* Check ESC-f, ESC-l, and ESC-c format specifiers.
+ Expected output:
+ a:10.5: one
+*/
+static void
+fmt_locus2 (mu_stream_t str)
+{
+ char *file = "a";
+ mu_stream_printf (str, "\033f<%d>%s\033l<%d>\033c<%d>one\n",
+ (int) strlen (file), file, 10, 5);
+}
+
+/* Check setting range with ESC-f, ESC-l, and ESC-c format specifiers.
+ Expected output:
+ a:10.5-b:14.8: one
+*/
+static void
+fmt_locus3 (mu_stream_t str)
+{
+ char *file[] = { "a", "b" };
+ mu_stream_printf (str, "\033f<%d>%s\033l<%d>\033c<%d>"
+ "\033f<%d>%s\033l<%d>\033c<%d>one\n",
+ (int) strlen (file[0]), file[0], 10, 5,
+ (int) strlen (file[1]), file[1], 14, 8);
+}
+
+/* Check that ESC-f, ESC-l, and ESC-c format specifiers don't clobber
+ default stream settings.
+ Expected output:
+ a:10.5-b:14.8: one
+ default
+*/
+static void
+fmt_locus4 (mu_stream_t str)
+{
+ char *file[] = { "a", "b" };
+ struct mu_locus_range lr;
+
+ lr.beg.mu_file = "input";
+ lr.beg.mu_line = 1;
+ lr.beg.mu_col = 1;
+
+ lr.end.mu_file = "next";
+ lr.end.mu_line = 5;
+ lr.end.mu_col = 10;
+
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &lr);
+
+ mu_stream_printf (str, "\033f<%d>%s\033l<%d>\033c<%d>"
+ "\033f<%d>%s\033l<%d>\033c<%d>one\n",
+ (int) strlen (file[0]), file[0], 10, 5,
+ (int) strlen (file[1]), file[1], 14, 8);
+ mu_stream_printf (str, "default\n");
+}
+
+/* Check that ESC-f, ESC-l, and ESC-c format specifiers don't clobber
+ default stream settings and locus.
+ Expected output:
+ a:10.5-b:14.8: one
+ input:1.1-next:5.10: default
+*/
+static void
+fmt_locus5 (mu_stream_t str)
+{
+ char *file[] = { "a", "b" };
+ struct mu_locus_range lr;
+ int mode;
+
+ lr.beg.mu_file = "input";
+ lr.beg.mu_line = 1;
+ lr.beg.mu_col = 1;
+
+ lr.end.mu_file = "next";
+ lr.end.mu_line = 5;
+ lr.end.mu_col = 10;
+
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &lr);
+
+ mode = MU_LOGMODE_LOCUS;
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
+ mu_stream_printf (str, "\033f<%d>%s\033l<%d>\033c<%d>"
+ "\033f<%d>%s\033l<%d>\033c<%d>one\n",
+ (int) strlen (file[0]), file[0], 10, 5,
+ (int) strlen (file[1]), file[1], 14, 8);
+ mu_stream_printf (str, "default\n");
+}
+
+/* Check the ESC-S specifier (store locus).
+ Expected output:
+ a:10.5-b:14.8: one
+ a:10.5-b:14.8: default
+*/
+static void
+fmt_locus6 (mu_stream_t str)
+{
+ char *file[] = { "a", "b" };
+ struct mu_locus_range lr;
+ int mode;
+
+ lr.beg.mu_file = "input";
+ lr.beg.mu_line = 1;
+ lr.beg.mu_col = 1;
+
+ lr.end.mu_file = "next";
+ lr.end.mu_line = 5;
+ lr.end.mu_col = 10;
+
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &lr);
+
+ mode = MU_LOGMODE_LOCUS;
+ mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
+ mu_stream_printf (str, "\033S\033f<%d>%s\033l<%d>\033c<%d>"
+ "\033f<%d>%s\033l<%d>\033c<%d>one\n",
+ (int) strlen (file[0]), file[0], 10, 5,
+ (int) strlen (file[1]), file[1], 14, 8);
+ mu_stream_printf (str, "default\n");
+}
+
+
+struct testcase
+{
+ char const *id;
+ void (*handler) (mu_stream_t);
+ int enabled;
+};
+
+struct testcase testcases[] = {
+ { "simple print", simple_print },
+ { "severity", check_severity },
+ { "suppress severity", check_suppress },
+ { "suppress severity name", check_suppress_name },
+ { "severity mask", check_severity_mask },
+ { "locus: file, line", lr_file_line },
+ { "locus: file, line, col", lr_file_line_col },
+ { "locus: file, line-range", lr_file_line2 },
+ { "locus: file, line-range, col", lr_file_line2_col },
+ { "locus: file-range, line-range, col-range", lr_file2_line_col },
+ { "set locus line", set_locus_line },
+ { "advance locus line", advance_locus_line },
+ { "set locus column", set_locus_col },
+ { "advance locus column", advance_locus_col },
+ { "fmt: severity", fmt_severity },
+ { "fmt: locus (file, line)", fmt_locus1 },
+ { "fmt: locus (file, line, column)", fmt_locus2 },
+ { "fmt: locus (range)", fmt_locus3 },
+ { "fmt: locus; restore defaults", fmt_locus4 },
+ { "fmt: locus; restore defaults, display locus", fmt_locus5 },
+ { "fmt: set locus", fmt_locus6 },
+ { NULL }
+};
+
+static mu_stream_t
+create_log (void)
+{
+ mu_stream_t str, transport;
+ int yes = 1;
+
+ MU_ASSERT (mu_stdio_stream_create (&transport, MU_STDOUT_FD, 0));
+ mu_stream_ioctl (transport, MU_IOCTL_FD, MU_IOCTL_FD_SET_BORROW, &yes);
+ MU_ASSERT (mu_log_stream_create (&str, transport));
+ mu_stream_unref (transport);
+ return str;
+}
+
+static void
+log_reset (mu_stream_t str)
+{
+ int mode = 0;
+ MU_ASSERT (mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_MODE, &mode));
+ MU_ASSERT (mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, NULL));
+ mode = 0;
+ MU_ASSERT (mu_stream_ioctl (str, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_SEVERITY_MASK,
+ &mode));
+}
+
+int
+main (int argc, char **argv)
+{
+ mu_stream_t log;
+ struct testcase *tp;
+ int i;
+ int ena = 0;
+
+ mu_set_program_name (argv[0]);
+ mu_stdstream_setup (MU_STDSTREAM_RESET_NONE);
+
+ if (argc > 1)
+ {
+ ena = 1;
+ for (i = 1; i < argc; i++)
+ {
+ char *p;
+ int n = strtol (argv[i], &p, 10);
+ if (! (*p == 0 && n >= 0) )
+ {
+ mu_error ("erroneous argument %s\n", argv[i]);
+ return 1;
+ }
+ testcases[n].enabled = ena;
+ }
+ }
+
+ log = create_log ();
+
+ for (i = 0, tp = testcases; tp->id; tp++, i++)
+ {
+ if (tp->enabled == ena)
+ {
+ mu_stream_printf (log, "%02d. %s\n", i, tp->id);
+ tp->handler (log);
+ log_reset (log);
+ }
+ }
+
+ return 0;
+}
+
+
diff --git a/libmailutils/tests/testsuite.at b/libmailutils/tests/testsuite.at
index d962bd6..f064462 100644
--- a/libmailutils/tests/testsuite.at
+++ b/libmailutils/tests/testsuite.at
@@ -153,6 +153,10 @@ m4_include([strin.at])
m4_include([strout.at])
m4_include([strerr.at])
+AT_BANNER([Streams])
+m4_include([logstr.at])
+m4_include([xscript.at])
+
m4_include([list.at])
m4_include([address.at])
m4_include([wordsplit.at])
@@ -209,4 +213,4 @@ m4_include([msgset.at])
m4_include([globtest.at])
-m4_include([xscript.at])
+m4_include([linetrack.at])
diff --git a/libmailutils/tests/wicket.c b/libmailutils/tests/wicket.c
index 1d77946..e5cf5b5 100644
--- a/libmailutils/tests/wicket.c
+++ b/libmailutils/tests/wicket.c
@@ -30,7 +30,7 @@ match_string (const char *str)
{
int rc;
mu_url_t u, url;
- struct mu_locus loc;
+ struct mu_locus_point loc;
if ((rc = mu_url_create (&u, str)) != 0)
{
diff --git a/libmailutils/tests/xscript.at b/libmailutils/tests/xscript.at
index 34189ba..47b2bea 100644
--- a/libmailutils/tests/xscript.at
+++ b/libmailutils/tests/xscript.at
@@ -14,7 +14,6 @@
# 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([Transcript stream])
AT_SETUP([Transcript stream])
AT_KEYWORDS([stream xscript])
AT_DATA([input],[first line
diff --git a/libmu_auth/radius.c b/libmu_auth/radius.c
index acd5634..68d3061 100644
--- a/libmu_auth/radius.c
+++ b/libmu_auth/radius.c
@@ -84,7 +84,8 @@ enum parse_state
state_lhs,
state_op,
state_rhs,
- state_delim
+ state_delim,
+ state_err
};
static int
@@ -96,7 +97,7 @@ cb_request (void *data, mu_config_value_t *val)
enum parse_state state;
grad_locus_t loc;
char *name;
- struct mu_locus locus;
+ struct mu_locus_range locus;
if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
return 1;
@@ -111,11 +112,11 @@ cb_request (void *data, mu_config_value_t *val)
}
if (mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
- MU_IOCTL_LOGSTREAM_GET_LOCUS,
+ MU_IOCTL_LOGSTREAM_GET_LOCUS_RANGE,
&locus) == 0)
{
- loc.file = locus.mu_file;
- loc.line = locus.mu_line;
+ loc.file = (char*) locus.beg.mu_file;
+ loc.line = locus.beg.mu_line;
}
else
{
@@ -123,7 +124,7 @@ cb_request (void *data, mu_config_value_t *val)
loc.line = 0;
}
- for (i = 0, state = state_lhs; i < ws.ws_wordc; i++)
+ for (i = 0, state = state_lhs; state != state_err && i < ws.ws_wordc; i++)
{
grad_avp_t *pair;
@@ -146,23 +147,36 @@ cb_request (void *data, mu_config_value_t *val)
if (!pair)
{
mu_error (_("cannot create radius A/V pair `%s'"), name);
- return 1;
+ state = state_err;
+ }
+ else
+ {
+ grad_avl_merge (plist, &pair);
+ state = state_delim;
}
- grad_avl_merge (plist, &pair);
- state = state_delim;
break;
case state_delim:
if (strcmp (ws.ws_wordv[i], ","))
{
mu_error (_("expected `,' but found `%s'"), ws.ws_wordv[i]);
- return 1;
+ state = state_err;
}
- state = state_lhs;
+ else
+ state = state_lhs;
+ break;
+
+ default:
+ abort ();
}
}
- mu_wordsplit_free (&ws);
+ mu_wordsplit_free (&ws);
+ mu_locus_range_deinit (&locus);
+
+ if (state == state_err)
+ return 1;
+
if (state != state_delim && state != state_delim)
{
mu_error (_("malformed radius A/V list"));
diff --git a/libmu_sieve/Makefile.am b/libmu_sieve/Makefile.am
index 1e75e33..2954794 100644
--- a/libmu_sieve/Makefile.am
+++ b/libmu_sieve/Makefile.am
@@ -15,7 +15,7 @@
## You should have received a copy of the GNU General Public License
## along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
-YLWRAP = $(SHELL) $(mu_aux_dir)/gylwrap
+YLWRAP = @MU_YLWRAP@
AM_YFLAGS = -dtv
#AM_LEXFLAGS=-dvp
AM_CPPFLAGS =\
@@ -39,9 +39,8 @@ libmu_sieve_la_SOURCES = \
relational.c\
require.c\
runtime.c\
- sieve-gram.c\
- sieve-gram.h\
- sieve-lex.c\
+ sieve-gram.y\
+ sieve-lex.l\
strexp.c\
string.c\
tests.c\
@@ -50,24 +49,14 @@ libmu_sieve_la_SOURCES = \
libmu_sieve_la_LIBADD = ${MU_LIB_MAILUTILS} @LTDL_LIB@
libmu_sieve_la_LDFLAGS = -version-info @VI_CURRENT@:@VI_REVISION@:@VI_AGE@
-noinst_HEADERS = sieve-priv.h
+noinst_HEADERS = sieve-priv.h sieve-gram.h
BUILT_SOURCES = \
sieve-gram.c sieve-gram.h \
sieve-lex.c
-MAINTAINERCLEANFILES=$(BUILT_SOURCES)
-
-EXTRA_DIST = sieve.y sieve.l
+EXTRA_DIST=gylwrap.conf
-sieve-lex.c: $(srcdir)/sieve.l sieve-gram.h
- $(YLWRAP) "$(LEX) $(AM_LEXFLAGS) $(LEXFLAGS)" \
- $(srcdir)/sieve.l lex.yy.c sieve-lex.c \
- -- -yy mu_sieve_yy
-
-sieve-gram.c sieve-gram.h: $(srcdir)/sieve.y
- $(YLWRAP) "$(YACC) $(AM_YFLAGS) $(YFLAGS)" $(srcdir)/sieve.y \
- y.tab.c sieve-gram.c y.tab.h sieve-gram.h y.output y.output \
- -- -yy mu_sieve_yy
+MAINTAINERCLEANFILES=$(BUILT_SOURCES)
diff --git a/libmu_sieve/actions.c b/libmu_sieve/actions.c
index 93b33e0..39b66fc 100644
--- a/libmu_sieve/actions.c
+++ b/libmu_sieve/actions.c
@@ -528,8 +528,8 @@ perms_tag_checker (mu_sieve_machine_t mach)
{
if (mu_parse_stream_perm_string (&flag, t->v.string, &p))
{
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
- _("invalid permissions (near %s)"), p);
+ mu_diag_at_locus_range (MU_LOG_ERROR, &t->locus,
+ _("invalid permissions (near %s)"), p);
mu_i_sv_error (mach);
err = 1;
}
diff --git a/libmu_sieve/comparator.c b/libmu_sieve/comparator.c
index 8b7e583..1a3be1a 100644
--- a/libmu_sieve/comparator.c
+++ b/libmu_sieve/comparator.c
@@ -174,7 +174,7 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach)
{
if (match)
{
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
+ mu_diag_at_locus_range (MU_LOG_ERROR, &t->locus,
_("match type specified twice in call to `%s'"),
mach->identifier);
mu_i_sv_error (mach);
@@ -209,7 +209,7 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach)
if (compname && strcmp (compname, "i;ascii-numeric"))
{
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
+ mu_diag_at_locus_range (MU_LOG_ERROR, &match->locus,
/* TRANSLATORS: Do not translate ':count'.
It is the name of a Sieve tag */
_("comparator %s is incompatible with "
@@ -235,7 +235,7 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach)
break;
/* fall through */
default:
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
+ mu_diag_at_locus_range (MU_LOG_ERROR, &val->locus,
_(":count requires second argument to be a list of one element"));
mu_i_sv_error (mach);
return 1;
@@ -246,7 +246,7 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach)
char *p = mu_str_skip_class (argstr->orig, MU_CTYPE_DIGIT);
if (*p)
{
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
+ mu_diag_at_locus_range (MU_LOG_ERROR, &val->locus,
_("second argument cannot be converted to number"));
mu_i_sv_error (mach);
return 1;
@@ -258,7 +258,7 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach)
if (mu_sieve_str_to_relcmp (str, NULL, NULL))
{
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
+ mu_diag_at_locus_range (MU_LOG_ERROR, &match->locus,
_("invalid relational match `%s' in call to `%s'"),
str, mach->identifier);
mu_i_sv_error (mach);
@@ -278,10 +278,16 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach)
compfun = mu_sieve_comparator_lookup (mach, compname, matchtype);
if (!compfun)
{
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
+ if (match)
+ mu_diag_at_locus_range (MU_LOG_ERROR, &match->locus,
+ _("comparator `%s' is incompatible with match type `%s' in call to `%s'"),
+ compname, match->tag,
+ mach->identifier);
+ else
+ mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus,
_("comparator `%s' is incompatible with match type `%s' in call to `%s'"),
- compname, match ? match->tag : "is",
- mach->identifier);
+ compname, "is",
+ mach->identifier);
mu_i_sv_error (mach);
return 1;
}
diff --git a/libmu_sieve/extensions/moderator.c b/libmu_sieve/extensions/moderator.c
index 5ec61d2..f82e615 100644
--- a/libmu_sieve/extensions/moderator.c
+++ b/libmu_sieve/extensions/moderator.c
@@ -103,7 +103,7 @@ moderator_filter_message (mu_sieve_machine_t mach,
}
else if (mu_sieve_get_tag (mach, "program", SVT_STRING, &arg))
{
- struct mu_locus locus;
+ struct mu_locus_range locrange = MU_LOCUS_RANGE_INITIALIZER;
rc = mu_sieve_machine_clone (mach, &newmach);
if (rc)
@@ -112,10 +112,10 @@ moderator_filter_message (mu_sieve_machine_t mach,
mu_strerror (rc));
return 1;
}
- mu_sieve_get_locus (mach, &locus);
- rc = mu_sieve_compile_buffer (newmach,
- arg, strlen (arg),
- locus.mu_file, locus.mu_line);
+ mu_sieve_get_locus (mach, &locrange);
+ rc = mu_sieve_compile_text (newmach,
+ arg, strlen (arg),
+ &locrange.beg);
if (rc)
mu_sieve_error (mach, _("cannot compile subprogram"));
}
diff --git a/libmu_sieve/gylwrap.conf b/libmu_sieve/gylwrap.conf
new file mode 100644
index 0000000..3f574d7
--- a/dev/null
+++ b/libmu_sieve/gylwrap.conf
@@ -0,0 +1,4 @@
+# Configuration settings for gylwrap.
+# See ../mu-aux/gylwrap --help, for details.
+
+yyrepl=mu_sieve_yy
diff --git a/libmu_sieve/mem.c b/libmu_sieve/mem.c
index 5a89fa8..f98e747 100644
--- a/libmu_sieve/mem.c
+++ b/libmu_sieve/mem.c
@@ -218,7 +218,7 @@ mu_i_sv_2nrealloc (mu_sieve_machine_t mach, void **pptr, size_t *pnmemb,
worth the trouble. */
if ((size_t) -1 / 3 * 2 / size <= nmemb)
{
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
+ mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus,
_("requested too much memory %zu * %zu"),
nmemb, size);
mu_sieve_abort (mach);
@@ -232,19 +232,19 @@ mu_i_sv_2nrealloc (mu_sieve_machine_t mach, void **pptr, size_t *pnmemb,
*pnmemb = nmemb;
}
-char *
-mu_i_sv_id_canon (mu_sieve_machine_t mach, char const *name)
+size_t
+mu_i_sv_id_num (mu_sieve_machine_t mach, char const *name)
{
size_t i;
char *p;
if (!name)
- return NULL;
+ abort ();
for (i = 0; i < mach->idcount; i++)
{
if (strcmp (mach->idspace[i], name) == 0)
- return mach->idspace[i];
+ return i;
}
if (mach->idcount == mach->idmax)
@@ -256,24 +256,11 @@ mu_i_sv_id_canon (mu_sieve_machine_t mach, char const *name)
}
p = mu_sieve_strdup (mach, name);
- mach->idspace[mach->idcount++] = p;
+ mach->idspace[mach->idcount] = p;
- return p;
+ return mach->idcount++;
}
-size_t
-mu_i_sv_id_num (mu_sieve_machine_t mach, char const *name)
-{
- size_t i;
-
- for (i = 0; i < mach->idcount; i++)
- {
- if (mach->idspace[i] == name || strcmp (mach->idspace[i], name) == 0)
- return i;
- }
- abort ();
-}
-
char *
mu_i_sv_id_str (mu_sieve_machine_t mach, size_t n)
{
diff --git a/libmu_sieve/prog.c b/libmu_sieve/prog.c
index dc2ae93..70e0453 100644
--- a/libmu_sieve/prog.c
+++ b/libmu_sieve/prog.c
@@ -35,32 +35,48 @@ mu_i_sv_code (struct mu_sieve_machine *mach, sieve_op_t op)
mach->prog[mach->pc++] = op;
}
-static int
-file_eq (char const *a, char const *b)
-{
- if (a)
- return b ? (strcmp (a, b) == 0) : 1;
- return b ? 0 : 1;
-}
-
-/* FIXME: 1. Only beg is stored
- 2. mu_col is not used
- */
int
mu_i_sv_locus (struct mu_sieve_machine *mach, struct mu_locus_range *lr)
{
- if (!file_eq (mach->locus.mu_file, lr->beg.mu_file))
+ if (!mu_locus_point_same_file (&mach->locus.beg, &lr->beg))
{
mu_i_sv_code (mach, (sieve_op_t) _mu_i_sv_instr_source);
mu_i_sv_code (mach, (sieve_op_t) mu_i_sv_id_num (mach, lr->beg.mu_file));
+ mu_i_sv_code (mach, (sieve_op_t) (int) 0);
}
- if (mach->locus.mu_line != lr->beg.mu_line)
+ if (mach->locus.beg.mu_line != lr->beg.mu_line)
{
mu_i_sv_code (mach, (sieve_op_t) _mu_i_sv_instr_line);
mu_i_sv_code (mach, (sieve_op_t) lr->beg.mu_line);
+ mu_i_sv_code (mach, (sieve_op_t) (int) 0);
+ }
+ if (mach->locus.beg.mu_col != lr->beg.mu_col)
+ {
+ mu_i_sv_code (mach, (sieve_op_t) _mu_i_sv_instr_col);
+ mu_i_sv_code (mach, (sieve_op_t) lr->beg.mu_col);
+ mu_i_sv_code (mach, (sieve_op_t) (int) 0);
+ }
+
+ if (!mu_locus_point_same_file (&mach->locus.end, &lr->end))
+ {
+ mu_i_sv_code (mach, (sieve_op_t) _mu_i_sv_instr_source);
+ mu_i_sv_code (mach, (sieve_op_t) mu_i_sv_id_num (mach, lr->end.mu_file));
+ mu_i_sv_code (mach, (sieve_op_t) (int) 1);
+ }
+ if (mach->locus.end.mu_line != lr->end.mu_line)
+ {
+ mu_i_sv_code (mach, (sieve_op_t) _mu_i_sv_instr_line);
+ mu_i_sv_code (mach, (sieve_op_t) lr->end.mu_line);
+ mu_i_sv_code (mach, (sieve_op_t) (int) 1);
+ }
+ if (mach->locus.end.mu_col != lr->end.mu_col)
+ {
+ mu_i_sv_code (mach, (sieve_op_t) _mu_i_sv_instr_col);
+ mu_i_sv_code (mach, (sieve_op_t) lr->end.mu_col);
+ mu_i_sv_code (mach, (sieve_op_t) (int) 1);
}
- mach->locus = lr->beg;
+ mu_locus_range_copy (&mach->locus, lr);
return 0;
}
@@ -155,7 +171,7 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach,
if (!tag)
{
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
+ mu_diag_at_locus_range (MU_LOG_ERROR, &val->locus,
_("invalid tag name `%s' for `%s'"),
val->v.string, reg->name);
mu_i_sv_error (mach);
@@ -175,7 +191,8 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach,
{
if (i + 1 == node->v.command.argcount)
{
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
+ /* FIXME: more exact locus */
+ mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus,
_("required argument for tag %s is missing"),
tag->name);
mu_i_sv_error (mach);
@@ -192,11 +209,11 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach,
if (val->type != tag->argtype)
{
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
+ mu_diag_at_locus_range (MU_LOG_ERROR, &val->locus,
_("type mismatch in argument to "
"tag `%s'"),
tag->name);
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
+ mu_diag_at_locus_range (MU_LOG_ERROR, &val->locus,
_("expected %s but passed %s"),
mu_sieve_type_str (tag->argtype),
mu_sieve_type_str (val->type));
@@ -210,7 +227,7 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach,
{
if (!chk_list && (rc = mu_list_create (&chk_list)))
{
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
+ mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus,
_("cannot create check list: %s"),
mu_strerror (rc));
mu_i_sv_error (mach);
@@ -222,7 +239,7 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach,
rc = mu_list_append (chk_list, cf);
if (rc)
{
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
+ mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus,
"mu_list_append: %s",
mu_strerror (rc));
mu_i_sv_error (mach);
@@ -243,7 +260,7 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach,
}
else
{
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
+ mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus,
_("too many arguments in call to `%s'"),
reg->name);
mu_i_sv_error (mach);
@@ -258,11 +275,11 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach,
/* compatible types */;
else
{
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
+ mu_diag_at_locus_range (MU_LOG_ERROR, &val->locus,
_("type mismatch in argument %lu to `%s'"),
(unsigned long) (exp_arg - reg->v.command.req_args + 1),
reg->name);
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
+ mu_diag_at_locus_range (MU_LOG_ERROR, &val->locus,
_("expected %s but passed %s"),
mu_sieve_type_str (*exp_arg),
mu_sieve_type_str (val->type));
@@ -277,9 +294,9 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach,
if (!err && !opt_args && *exp_arg != SVT_VOID)
{
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
- _("too few arguments in call to `%s'"),
- reg->name);
+ mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus,
+ _("too few arguments in call to `%s'"),
+ reg->name);
mu_i_sv_error (mach);
err = 1;
}
diff --git a/libmu_sieve/require.c b/libmu_sieve/require.c
index 597af98..b5c9699 100644
--- a/libmu_sieve/require.c
+++ b/libmu_sieve/require.c
@@ -56,7 +56,7 @@ mu_sieve_require (mu_sieve_machine_t mach, mu_sieve_slice_t list)
if (rc)
{
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus, _("can't require %s"),
+ mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus, _("can't require %s"),
name);
mu_i_sv_error (mach);
}
diff --git a/libmu_sieve/runtime.c b/libmu_sieve/runtime.c
index c5c1ab5..b18b996 100644
--- a/libmu_sieve/runtime.c
+++ b/libmu_sieve/runtime.c
@@ -34,26 +34,46 @@
void
_mu_i_sv_instr_source (mu_sieve_machine_t mach)
{
- mach->locus.mu_file = mu_i_sv_id_str (mach, SIEVE_RT_ARG (mach, 0, pc));
- mu_stream_ioctl (mach->errstream, MU_IOCTL_LOGSTREAM,
- MU_IOCTL_LOGSTREAM_SET_LOCUS,
- &mach->locus);
+ char const *file = mu_i_sv_id_str (mach, SIEVE_RT_ARG (mach, 0, pc));
+ int what = SIEVE_RT_ARG (mach, 1, inum);
+ mu_locus_point_set_file (what ? &mach->locus.beg : &mach->locus.end, file);
if (INSTR_DEBUG (mach))
- mu_i_sv_debug (mach, mach->pc - 1, "SOURCE %s", mach->locus.mu_file);
- SIEVE_RT_ADJUST (mach, 1);
+ mu_i_sv_debug (mach, mach->pc - 2, "SOURCE %s %d", file, what);
+ SIEVE_RT_ADJUST (mach, 2);
+ mu_stream_ioctl (mach->errstream, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &mach->locus);
}
void
_mu_i_sv_instr_line (mu_sieve_machine_t mach)
{
- mach->locus.mu_line = SIEVE_RT_ARG (mach, 0, line);
+ unsigned line = SIEVE_RT_ARG (mach, 0, line);
+ int what = SIEVE_RT_ARG (mach, 1, inum);
+ if (what == 0)
+ mach->locus.beg.mu_line = line;
+ else
+ mach->locus.end.mu_line = line;
+ if (INSTR_DEBUG (mach))
+ mu_i_sv_debug (mach, mach->pc - 1, "LINE %u %d", line, what);
+ SIEVE_RT_ADJUST (mach, 2);
mu_stream_ioctl (mach->errstream, MU_IOCTL_LOGSTREAM,
- MU_IOCTL_LOGSTREAM_SET_LOCUS,
- &mach->locus);
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &mach->locus);
+}
+
+void
+_mu_i_sv_instr_col (mu_sieve_machine_t mach)
+{
+ unsigned col = SIEVE_RT_ARG (mach, 0, line);
+ int what = SIEVE_RT_ARG (mach, 1, inum);
+ if (what == 0)
+ mach->locus.beg.mu_col = col;
+ else
+ mach->locus.end.mu_col = col;
if (INSTR_DEBUG (mach))
- mu_i_sv_debug (mach, mach->pc - 1, "LINE %u",
- mach->locus.mu_line);
- SIEVE_RT_ADJUST (mach, 1);
+ mu_i_sv_debug (mach, mach->pc - 2, "COLUMN %u %d", col, what);
+ SIEVE_RT_ADJUST (mach, 2);
+ mu_stream_ioctl (mach->errstream, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &mach->locus);
}
static int
@@ -173,14 +193,9 @@ mu_sieve_get_data (mu_sieve_machine_t mach)
}
int
-mu_sieve_get_locus (mu_sieve_machine_t mach, struct mu_locus *loc)
+mu_sieve_get_locus (mu_sieve_machine_t mach, struct mu_locus_range *loc)
{
- if (mach->locus.mu_file)
- {
- *loc = mach->locus;
- return 0;
- }
- return 1;
+ return mu_locus_range_copy (loc, &mach->locus);
}
mu_mailbox_t
diff --git a/libmu_sieve/sieve.y b/libmu_sieve/sieve-gram.y
index 067489f..38a85b2 100644
--- a/libmu_sieve/sieve.y
+++ b/libmu_sieve/sieve-gram.y
@@ -36,44 +36,6 @@ static struct mu_sieve_node *node_alloc (enum mu_sieve_node_type,
static void node_list_add (struct mu_sieve_node_list *list,
struct mu_sieve_node *node);
-
-#define YYLLOC_DEFAULT(Current, Rhs, N) \
- do \
- { \
- if (N) \
- { \
- (Current).beg = YYRHSLOC(Rhs, 1).beg; \
- (Current).end = YYRHSLOC(Rhs, N).end; \
- } \
- else \
- { \
- (Current).beg = YYRHSLOC(Rhs, 0).end; \
- (Current).end = (Current).beg; \
- } \
- } while (0)
-
-#define LOCUS_EQ(a,b) \
- ((((a)->mu_file == (b)->mu_file) \
- || ((a)->mu_file && (b)->mu_file \
- && strcmp((a)->mu_file, (b)->mu_file) == 0)) \
- && (a)->mu_line == (b)->mu_line)
-
-#define YY_LOCATION_PRINT(File, Loc) \
- do \
- { \
- if (LOCUS_EQ(&(Loc).beg, &(Loc).end)) \
- fprintf(File, "%s:%u.%u-%u.%u", \
- (Loc).beg.mu_file, \
- (Loc).beg.mu_line, (Loc).beg.mu_col, \
- (Loc).end.mu_line, (Loc).end.mu_col); \
- else \
- fprintf(File, "%s:%u.%u-%s:%u.%u", \
- (Loc).beg.mu_file, \
- (Loc).beg.mu_line, (Loc).beg.mu_col, \
- (Loc).end.mu_file, \
- (Loc).end.mu_line, (Loc).end.mu_col); \
- } \
- while (0)
%}
%error-verbose
@@ -87,6 +49,7 @@ static void node_list_add (struct mu_sieve_node_list *list,
struct
{
char *ident;
+ struct mu_locus_range idloc;
size_t first;
size_t count;
} command;
@@ -242,21 +205,21 @@ test : command
{
mu_sieve_registry_t *reg;
- mu_sieve_machine->locus = @1.beg;
+ mu_locus_range_copy (&mu_sieve_machine->locus, &@1);
reg = mu_sieve_registry_lookup (mu_sieve_machine, $1.ident,
mu_sieve_record_test);
if (!reg)
{
- mu_diag_at_locus (MU_LOG_ERROR, &@1.beg,
- _("unknown test: %s"),
- $1.ident);
+ mu_diag_at_locus_range (MU_LOG_ERROR, &$1.idloc,
+ _("unknown test: %s"),
+ $1.ident);
mu_i_sv_error (mu_sieve_machine);
}
else if (!reg->required)
{
- mu_diag_at_locus (MU_LOG_ERROR, &@1.beg,
- _("test `%s' has not been required"),
- $1.ident);
+ mu_diag_at_locus_range (MU_LOG_ERROR, &$1.idloc,
+ _("test `%s' has not been required"),
+ $1.ident);
mu_i_sv_error (mu_sieve_machine);
}
@@ -281,6 +244,7 @@ test : command
command : IDENT maybe_arglist
{
$$.ident = $1;
+ $$.idloc = @1;
$$.first = $2.first;
$$.count = $2.count;
}
@@ -290,22 +254,22 @@ action : command
{
mu_sieve_registry_t *reg;
- mu_sieve_machine->locus = @1.beg;
+ mu_locus_range_copy (&mu_sieve_machine->locus, &@1);
reg = mu_sieve_registry_lookup (mu_sieve_machine, $1.ident,
mu_sieve_record_action);
if (!reg)
{
- mu_diag_at_locus (MU_LOG_ERROR, &@1.beg,
- _("unknown action: %s"),
- $1.ident);
+ mu_diag_at_locus_range (MU_LOG_ERROR, &$1.idloc,
+ _("unknown action: %s"),
+ $1.ident);
mu_i_sv_error (mu_sieve_machine);
}
else if (!reg->required)
{
- mu_diag_at_locus (MU_LOG_ERROR, &@1.beg,
- _("action `%s' has not been required"),
- $1.ident);
+ mu_diag_at_locus_range (MU_LOG_ERROR, &$1.idloc,
+ _("action `%s' has not been required"),
+ $1.ident);
mu_i_sv_error (mu_sieve_machine);
}
@@ -341,23 +305,27 @@ arglist : arg
arg : stringlist
{
$$ = mu_sieve_value_create (mu_sieve_machine,
- SVT_STRING_LIST, &$1);
+ SVT_STRING_LIST, &@1, &$1);
}
| STRING
{
- $$ = mu_sieve_value_create (mu_sieve_machine, SVT_STRING, $1);
+ $$ = mu_sieve_value_create (mu_sieve_machine, SVT_STRING,
+ &@1, $1);
}
| MULTILINE
{
- $$ = mu_sieve_value_create (mu_sieve_machine, SVT_STRING, $1);
+ $$ = mu_sieve_value_create (mu_sieve_machine, SVT_STRING,
+ &@1, $1);
}
| NUMBER
{
- $$ = mu_sieve_value_create (mu_sieve_machine, SVT_NUMBER, &$1);
+ $$ = mu_sieve_value_create (mu_sieve_machine, SVT_NUMBER,
+ &@1, &$1);
}
| TAG
{
- $$ = mu_sieve_value_create (mu_sieve_machine, SVT_TAG, $1);
+ $$ = mu_sieve_value_create (mu_sieve_machine, SVT_TAG,
+ &@1, $1);
}
;
@@ -393,10 +361,7 @@ slist : STRING
int
yyerror (const char *s)
{
- extern struct mu_locus mu_sieve_locus;
-
- mu_sieve_machine->locus = mu_sieve_locus;
- mu_diag_at_locus (MU_LOG_ERROR, &mu_sieve_locus, "%s", s);
+ mu_error ("%s", s);
mu_i_sv_error (mu_sieve_machine);
return 0;
}
@@ -423,7 +388,8 @@ node_alloc (enum mu_sieve_node_type type, struct mu_locus_range *lr)
{
node->prev = node->next = NULL;
node->type = type;
- node->locus = *lr;
+ mu_locus_range_init (&node->locus);
+ mu_locus_range_copy (&node->locus, lr);
}
return node;
}
@@ -1104,15 +1070,9 @@ copy_stream_state (mu_sieve_machine_t child, mu_sieve_machine_t parent)
{
child->state_flags = parent->state_flags;
child->err_mode = parent->err_mode;
- child->err_locus = parent->err_locus;
- if (child->err_locus.mu_file)
- child->err_locus.mu_file =
- mu_sieve_strdup (child, child->err_locus.mu_file);
+ mu_locus_range_copy (&child->err_locus, &parent->err_locus);
child->dbg_mode = parent->dbg_mode;
- child->dbg_locus = parent->dbg_locus;
- if (child->dbg_locus.mu_file)
- child->dbg_locus.mu_file =
- mu_sieve_strdup (child, child->dbg_locus.mu_file);
+ mu_locus_range_copy (&child->dbg_locus, &parent->dbg_locus);
child->errstream = parent->errstream;
mu_stream_ref (child->errstream);
child->dbgstream = parent->dbgstream;
@@ -1266,9 +1226,9 @@ mu_sieve_machine_dup (mu_sieve_machine_t const in, mu_sieve_machine_t *out)
mach->state_flags = in->state_flags;
mach->err_mode = in->err_mode;
- mach->err_locus = in->err_locus;
+ mu_locus_range_copy (&mach->err_locus, &in->err_locus);
mach->dbg_mode = in->dbg_mode;
- mach->dbg_locus = in->dbg_locus;
+ mu_locus_range_copy (&mach->dbg_locus, &in->dbg_locus);
copy_stream_state (mach, in);
@@ -1456,8 +1416,7 @@ mu_sieve_machine_destroy (mu_sieve_machine_t *pmach)
}
int
-with_machine (mu_sieve_machine_t mach, char const *name,
- int (*thunk) (void *), void *data)
+with_machine (mu_sieve_machine_t mach, int (*thunk) (void *), void *data)
{
int rc = 0;
mu_stream_t save_errstr;
@@ -1523,11 +1482,21 @@ static int
sieve_parse (void)
{
int rc;
+ int old_mode, mode;
sieve_tree = NULL;
yydebug = mu_debug_level_p (mu_sieve_debug_handle, MU_DEBUG_TRACE3);
+ mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_GET_MODE, &old_mode);
+ mode = old_mode | MU_LOGMODE_LOCUS;
+ mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
+
rc = yyparse ();
+ mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_MODE, &old_mode);
+
mu_i_sv_lex_finish ();
if (rc)
mu_i_sv_error (mu_sieve_machine);
@@ -1547,9 +1516,8 @@ sieve_parse (void)
mu_i_sv_code (mu_sieve_machine, (sieve_op_t) (sieve_instr_t) 0);
/* Clear location, so that mu_i_sv_locus will do its job. */
- mu_sieve_machine->locus.mu_file = NULL;
- mu_sieve_machine->locus.mu_line = 0;
- mu_sieve_machine->locus.mu_col = 0;
+ /* FIXME: is it still needed? */
+ mu_locus_range_deinit (&mu_sieve_machine->locus);
tree_code (mu_sieve_machine, sieve_tree);
mu_i_sv_code (mu_sieve_machine, (sieve_op_t) (sieve_instr_t) 0);
@@ -1581,39 +1549,50 @@ sieve_compile_file (void *name)
int
mu_sieve_compile (mu_sieve_machine_t mach, const char *name)
{
- return with_machine (mach, name, sieve_compile_file, (void *) name);
+ return with_machine (mach, sieve_compile_file, (void *) name);
}
struct strbuf
{
const char *ptr;
size_t size;
- const char *file;
- int line;
+ struct mu_locus_point const *pt;
};
static int
sieve_compile_strbuf (void *name)
{
struct strbuf *buf = name;
- if (mu_i_sv_lex_begin_string (buf->ptr, buf->size, buf->file, buf->line) == 0)
+ if (mu_i_sv_lex_begin_string (buf->ptr, buf->size, buf->pt) == 0)
return sieve_parse ();
return MU_ERR_FAILURE;
}
int
-mu_sieve_compile_buffer (mu_sieve_machine_t mach,
- const char *str, int strsize,
- const char *fname, int line)
+mu_sieve_compile_text (mu_sieve_machine_t mach,
+ const char *str, size_t strsize,
+ struct mu_locus_point const *loc)
{
struct strbuf buf;
buf.ptr = str;
buf.size = strsize;
- buf.file = fname;
- buf.line = line;
- return with_machine (mach, fname, sieve_compile_strbuf, &buf);
+ buf.pt = loc;
+ return with_machine (mach, sieve_compile_strbuf, &buf);
}
+int
+mu_sieve_compile_buffer (mu_sieve_machine_t mach,
+ const char *buf, int bufsize,
+ const char *fname, int line)
+{
+ int rc;
+ struct mu_locus_point loc = MU_LOCUS_POINT_INITIALIZER;
+ mu_locus_point_set_file (&loc, fname);
+ loc.mu_line = line;
+ rc = mu_sieve_compile_text (mach, buf, bufsize, &loc);
+ mu_locus_point_deinit (&loc);
+ return rc;
+}
diff --git a/libmu_sieve/sieve.l b/libmu_sieve/sieve-lex.l
index 099fc77..fd145bf 100644
--- a/libmu_sieve/sieve.l
+++ b/libmu_sieve/sieve-lex.l
@@ -54,10 +54,8 @@ static void sieve_searchpath (void);
static char *str_unescape (char *text, size_t len);
static int isemptystr (char *text);
+static mu_linetrack_t trk;
static ino_t sieve_source_inode;
-struct mu_locus mu_sieve_locus;
-static int newline;
-
static mu_stream_t input_stream;
static int
@@ -71,8 +69,10 @@ fillbuf (char *buf, size_t max_size)
rc = mu_stream_read (input_stream, buf, max_size, &max_size);
if (rc)
{
- mu_diag_funcall (MU_DIAG_ERROR, "mu_stream_read",
- mu_sieve_locus.mu_file, rc);
+ struct mu_locus_point pt;
+ mu_linetrack_locus (trk, &pt);
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_stream_read", pt.mu_file, rc);
+ mu_locus_point_deinit (&pt);
return 0;
}
return max_size;
@@ -90,40 +90,33 @@ fillbuf (char *buf, size_t max_size)
yy_switch_to_buffer (s); \
} while (0)
-static void
-init_locus (char const *name, ino_t ino)
-{
- mu_sieve_locus.mu_file = mu_i_sv_id_canon (mu_sieve_machine, name);
- mu_sieve_locus.mu_line = 1;
- mu_sieve_locus.mu_col = 0;
- newline = 0;
- sieve_source_inode = ino;
-}
+#define YY_USER_ACTION \
+ do \
+ { \
+ mu_linetrack_advance (trk, &yylloc, yytext, yyleng); \
+ mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, \
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &yylloc); \
+ } \
+ while (0);
+
static void
-advance_locus (void)
+init_locus (char const *name, ino_t ino)
{
- if (newline)
+ if (name)
{
- mu_sieve_locus.mu_line++;
- mu_sieve_locus.mu_col = 0;
- yylloc.beg = yylloc.end = mu_sieve_locus;
+ MU_ASSERT (mu_linetrack_create (&trk, name, 2));
}
else
- {
- mu_sieve_locus.mu_col += yyleng;
- yylloc.beg = yylloc.end = mu_sieve_locus;
- yylloc.beg.mu_col -= yyleng;
- }
- newline = yytext[yyleng-1] == '\n';
+ mu_linetrack_destroy (&trk);
+ sieve_source_inode = ino;
}
-
-#define YY_USER_ACTION advance_locus ();
struct buffer_ctx
{
struct buffer_ctx *prev;
- struct mu_locus locus;
+ mu_linetrack_t trk;
+ struct mu_locus_range incl_range;
ino_t i_node;
mu_stream_t input;
LEX_BUFFER_STATE state;
@@ -156,13 +149,12 @@ push_source (const char *name)
if (stat (name, &st))
{
- mu_diag_at_locus (MU_LOG_ERROR, &mu_sieve_locus,
- _("cannot stat `%s': %s"), name, strerror (errno));
+ mu_error (_("cannot stat `%s': %s"), name, strerror (errno));
mu_i_sv_error (mu_sieve_machine);
return 1;
}
- if (mu_sieve_locus.mu_file && st.st_ino == sieve_source_inode)
+ if (yylloc.beg.mu_file && st.st_ino == sieve_source_inode)
{
yyerror (_("recursive inclusion"));
return 1;
@@ -172,16 +164,14 @@ push_source (const char *name)
yyerror (_("recursive inclusion"));
if (ctx->prev)
{
- mu_diag_at_locus (MU_LOG_ERROR, &ctx->prev->locus,
- _("`%s' already included here"),
- name);
+ mu_diag_at_locus_range (MU_LOG_ERROR, &ctx->incl_range,
+ _("`%s' already included here"),
+ name);
mu_i_sv_error (mu_sieve_machine);
}
else
{
- mu_diag_at_locus (MU_LOG_ERROR, &mu_sieve_locus,
- _("`%s' already included at top level"),
- name);
+ mu_error (_("`%s' already included at top level"), name);
mu_i_sv_error (mu_sieve_machine);
}
return 1;
@@ -190,19 +180,17 @@ push_source (const char *name)
rc = mu_file_stream_create (&stream, name, MU_STREAM_READ);
if (rc)
{
- mu_diag_at_locus (MU_LOG_ERROR, &mu_sieve_locus,
- _("cannot open file `%s': %s"),
- name, mu_strerror (rc));
+ mu_error (_("cannot open file `%s': %s"), name, mu_strerror (rc));
mu_i_sv_error (mu_sieve_machine);
return 1;
}
/* Push current context */
- if (mu_sieve_locus.mu_file)
+ if (trk)
{
- advance_locus ();
ctx = mu_sieve_malloc (mu_sieve_machine, sizeof (*ctx));
- ctx->locus = mu_sieve_locus;
+ ctx->trk = trk;
+ mu_locus_range_copy (&ctx->incl_range, &yylloc);
ctx->i_node = sieve_source_inode;
ctx->input = input_stream;
ctx->prev = context_stack;
@@ -233,7 +221,9 @@ pop_source ()
}
/* Restore previous context */
input_stream = context_stack->input;
- mu_sieve_locus = context_stack->locus;
+ mu_linetrack_destroy (&trk);
+ trk = context_stack->trk;
+ mu_locus_range_deinit (&context_stack->incl_range);
sieve_source_inode = context_stack->i_node;
RESTORE_BUFFER_STATE (context_stack->state);
ctx = context_stack->prev;
@@ -449,12 +439,10 @@ mu_i_sv_lex_begin (const char *name)
int
mu_i_sv_lex_begin_string (const char *buf, int bufsize,
- const char *fname, int line)
+ struct mu_locus_point const *pt)
{
int rc;
- if (!fname)
- return 1;
yyrestart (NULL);
rc = mu_static_memory_stream_create (&input_stream, buf, bufsize);
@@ -465,7 +453,8 @@ mu_i_sv_lex_begin_string (const char *buf, int bufsize,
return 1;
}
- init_locus (fname, 0);
+ init_locus (pt->mu_file, 0);
+ mu_linetrack_rebase (trk, pt);
return 0;
}
@@ -643,9 +632,7 @@ line_finish (void)
}
else if (rc != MU_ERR_CANCELED)
{
- mu_diag_at_locus (MU_LOG_ERROR, &mu_sieve_locus,
- _("error expandind string: %s"),
- mu_strerror (rc));
+ mu_error (_("error expandind string: %s"), mu_strerror (rc));
}
}
yylval.string = str;
diff --git a/libmu_sieve/sieve-priv.h b/libmu_sieve/sieve-priv.h
index 041b4ea..ba5bad9 100644
--- a/libmu_sieve/sieve-priv.h
+++ b/libmu_sieve/sieve-priv.h
@@ -18,6 +18,8 @@
#include <mailutils/sieve.h>
#include <mailutils/assoc.h>
+#include <mailutils/locus.h>
+#include <mailutils/yyloc.h>
#include <setjmp.h>
#include <string.h>
#include <regex.h>
@@ -38,13 +40,6 @@ typedef union
unsigned unum;
} sieve_op_t;
-struct mu_locus_range
-{
- struct mu_locus beg;
- struct mu_locus end;
-};
-
-#define YYLTYPE struct mu_locus_range
#define MU_SV_SAVED_ERR_STATE 0x01
#define MU_SV_SAVED_DBG_STATE 0x02
@@ -62,7 +57,7 @@ enum mu_sieve_state
struct mu_sieve_machine
{
/* Static data */
- struct mu_locus locus; /* Approximate location in the code */
+ struct mu_locus_range locus; /* Approximate location in the code */
mu_list_t memory_pool; /* Pool of allocated memory objects */
mu_list_t destr_list; /* List of destructor functions */
@@ -118,9 +113,9 @@ struct mu_sieve_machine
/* Stream state info */
int state_flags;
int err_mode;
- struct mu_locus err_locus;
+ struct mu_locus_range err_locus;
int dbg_mode;
- struct mu_locus dbg_locus;
+ struct mu_locus_range dbg_locus;
/* User supplied data */
mu_stream_t errstream;
@@ -182,7 +177,7 @@ int mu_sieve_yylex (void);
int mu_i_sv_lex_begin (const char *name);
int mu_i_sv_lex_begin_string (const char *buf, int bufsize,
- const char *fname, int line);
+ struct mu_locus_point const *pt);
void mu_i_sv_lex_finish (void);
extern mu_sieve_machine_t mu_sieve_machine;
@@ -204,6 +199,7 @@ void _mu_i_sv_instr_brz (mu_sieve_machine_t mach);
void _mu_i_sv_instr_brnz (mu_sieve_machine_t mach);
void _mu_i_sv_instr_source (mu_sieve_machine_t mach);
void _mu_i_sv_instr_line (mu_sieve_machine_t mach);
+void _mu_i_sv_instr_col (mu_sieve_machine_t mach);
int mu_i_sv_load_add_dir (mu_sieve_machine_t mach, const char *name);
@@ -244,7 +240,6 @@ void mu_i_sv_lint_command (struct mu_sieve_machine *mach,
size_t mu_i_sv_string_create (mu_sieve_machine_t mach, char *str);
-char *mu_i_sv_id_canon (mu_sieve_machine_t mach, char const *name);
size_t mu_i_sv_id_num (mu_sieve_machine_t mach, char const *name);
char *mu_i_sv_id_str (mu_sieve_machine_t mach, size_t n);
void mu_i_sv_free_idspace (mu_sieve_machine_t mach);
diff --git a/libmu_sieve/util.c b/libmu_sieve/util.c
index 7cc9227..3d4763c 100644
--- a/libmu_sieve/util.c
+++ b/libmu_sieve/util.c
@@ -28,6 +28,7 @@
size_t
mu_sieve_value_create (mu_sieve_machine_t mach, mu_sieve_data_type type,
+ struct mu_locus_range const *locus,
void *data)
{
size_t idx;
@@ -43,6 +44,18 @@ mu_sieve_value_create (mu_sieve_machine_t mach, mu_sieve_data_type type,
memset (val, 0, sizeof *val);
val->type = type;
+
+ /* Copy locus. */
+ val->locus.beg.mu_file =
+ mu_i_sv_id_str (mach, mu_i_sv_id_num (mach, locus->beg.mu_file));
+ val->locus.beg.mu_line = locus->beg.mu_line;
+ val->locus.beg.mu_col = locus->beg.mu_col;
+ val->locus.end.mu_file =
+ mu_i_sv_id_str (mach, mu_i_sv_id_num (mach, locus->end.mu_file));
+ val->locus.end.mu_line = locus->end.mu_line;
+ val->locus.end.mu_col = locus->end.mu_col;
+
+ mu_locus_range_copy (&val->locus, locus);
switch (type)
{
case SVT_NUMBER:
@@ -205,12 +218,6 @@ mu_sieve_error (mu_sieve_machine_t mach, const char *fmt, ...)
va_start (ap, fmt);
mu_stream_printf (mach->errstream, "\033s<%d>", MU_LOG_ERROR);
- if (mach->locus.mu_file)
- mu_stream_printf (mach->errstream, "\033O<%d>\033f<%u>%s\033l<%u>",
- MU_LOGMODE_LOCUS,
- (unsigned) strlen (mach->locus.mu_file),
- mach->locus.mu_file,
- mach->locus.mu_line);
if (mach->identifier)
mu_stream_printf (mach->errstream, "%s: ", mach->identifier);
mu_stream_vprintf (mach->errstream, fmt, ap);
@@ -253,11 +260,11 @@ mu_i_sv_debug (mu_sieve_machine_t mach, size_t pc, const char *fmt, ...)
unsigned severity = MU_LOG_DEBUG;
mu_stream_ioctl (mach->dbgstream, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_SET_SEVERITY, &severity);
- if (mach->locus.mu_file)
+ if (mach->locus.beg.mu_file)
{
int mode = mach->dbg_mode | MU_LOGMODE_LOCUS;
mu_stream_ioctl (mach->dbgstream, MU_IOCTL_LOGSTREAM,
- MU_IOCTL_LOGSTREAM_SET_LOCUS, &mach->locus);
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &mach->locus);
mu_stream_ioctl (mach->dbgstream, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
}
@@ -281,11 +288,11 @@ mu_i_sv_debug_command (mu_sieve_machine_t mach,
unsigned severity = MU_LOG_DEBUG;
mu_stream_ioctl (mach->dbgstream, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_SET_SEVERITY, &severity);
- if (mach->locus.mu_file)
+ if (mach->locus.beg.mu_file)
{
int mode = mach->dbg_mode | MU_LOGMODE_LOCUS;
mu_stream_ioctl (mach->dbgstream, MU_IOCTL_LOGSTREAM,
- MU_IOCTL_LOGSTREAM_SET_LOCUS, &mach->locus);
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &mach->locus);
mu_stream_ioctl (mach->dbgstream, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
}
@@ -309,12 +316,6 @@ mu_i_sv_trace (mu_sieve_machine_t mach, const char *what)
return;
mu_stream_printf (mach->errstream, "\033s<%d>", MU_LOG_DEBUG);
- if (mach->locus.mu_file)
- mu_stream_printf (mach->errstream, "\033O<%d>\033f<%u>%s\033l<%u>",
- MU_LOGMODE_LOCUS,
- (unsigned) strlen (mach->locus.mu_file),
- mach->locus.mu_file,
- mach->locus.mu_line);
mu_stream_printf (mach->errstream, "%zu: %s %s", mach->msgno, what,
mach->identifier);
for (i = 0; i < mach->argcount; i++)
@@ -333,8 +334,6 @@ mu_sieve_log_action (mu_sieve_machine_t mach, const char *action,
if (!mach->logger)
return;
- mu_stream_ioctl (mach->errstream, MU_IOCTL_LOGSTREAM,
- MU_IOCTL_LOGSTREAM_SET_LOCUS, &mach->locus);
va_start (ap, fmt);
mach->logger (mach, action, fmt, ap);
va_end (ap);
@@ -479,13 +478,15 @@ mu_sieve_stream_save (mu_sieve_machine_t mach)
if (mu_stream_ioctl (mach->errstream, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_GET_MODE, &mach->err_mode) == 0
&& mu_stream_ioctl (mach->errstream, MU_IOCTL_LOGSTREAM,
- MU_IOCTL_LOGSTREAM_GET_LOCUS, &mach->err_locus) == 0)
+ MU_IOCTL_LOGSTREAM_GET_LOCUS_RANGE,
+ &mach->err_locus) == 0)
mach->state_flags |= MU_SV_SAVED_ERR_STATE;
if (mu_stream_ioctl (mach->dbgstream, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_GET_MODE, &mach->dbg_mode) == 0
&& mu_stream_ioctl (mach->dbgstream, MU_IOCTL_LOGSTREAM,
- MU_IOCTL_LOGSTREAM_GET_LOCUS, &mach->dbg_locus) == 0)
+ MU_IOCTL_LOGSTREAM_GET_LOCUS_RANGE,
+ &mach->dbg_locus) == 0)
mach->state_flags |= MU_SV_SAVED_DBG_STATE;
mach->state_flags |= MU_SV_SAVED_STATE;
@@ -502,7 +503,7 @@ mu_sieve_stream_restore (mu_sieve_machine_t mach)
mu_stream_ioctl (mach->errstream, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_SET_MODE, &mach->err_mode);
mu_stream_ioctl (mach->errstream, MU_IOCTL_LOGSTREAM,
- MU_IOCTL_LOGSTREAM_SET_LOCUS, &mach->err_locus);
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &mach->err_locus);
}
if (mach->dbgstream != mach->errstream
@@ -511,7 +512,7 @@ mu_sieve_stream_restore (mu_sieve_machine_t mach)
mu_stream_ioctl (mach->dbgstream, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_SET_MODE, &mach->dbg_mode);
mu_stream_ioctl (mach->dbgstream, MU_IOCTL_LOGSTREAM,
- MU_IOCTL_LOGSTREAM_SET_LOCUS, &mach->dbg_locus);
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &mach->dbg_locus);
}
mach->state_flags = 0;
diff --git a/libmu_sieve/variables.c b/libmu_sieve/variables.c
index 91550ef..ec24287 100644
--- a/libmu_sieve/variables.c
+++ b/libmu_sieve/variables.c
@@ -226,9 +226,12 @@ set_tag_checker (mu_sieve_machine_t mach)
*mu_sieve_get_tag_n (mach, j + 1) = *t;
else if (prec == tmp_prec)
{
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
- _("%s and %s can't be used together"),
- tmp.tag, t->tag);
+ mu_diag_at_locus_range (MU_LOG_ERROR, &t->locus,
+ _("%s and %s can't be used together"),
+ tmp.tag, t->tag);
+ mu_diag_at_locus_range (MU_LOG_ERROR, &tmp.locus,
+ _("%s encountered here"),
+ tmp.tag);
mu_i_sv_error (mach);
return 1;
}
diff --git a/mail/Makefile.am b/mail/Makefile.am
index 7c2cebc..b206151 100644
--- a/mail/Makefile.am
+++ b/mail/Makefile.am
@@ -15,6 +15,7 @@
## You should have received a copy of the GNU General Public License
## along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
+YLWRAP = @MU_YLWRAP@
AM_YFLAGS=-vt
AM_CPPFLAGS = \
@MU_APP_COMMON_INCLUDES@ @MU_AUTHINCS@\
diff --git a/mail/source.c b/mail/source.c
index 802e298..80b7929 100644
--- a/mail/source.c
+++ b/mail/source.c
@@ -49,7 +49,7 @@ mail_source (int argc, char **argv)
{
mu_stream_t input;
int save_term;
- struct mu_locus locus;
+ struct mu_locus_range locus = MU_LOCUS_RANGE_INITIALIZER;
int rc;
if (argc != 2)
@@ -69,15 +69,15 @@ mail_source (int argc, char **argv)
save_term = interactive;
interactive = 0;
- locus.mu_file = argv[1];
- locus.mu_line = 0;
- locus.mu_col = 0;
+ locus.beg.mu_file = argv[1];
+ locus.beg.mu_line = 0;
+ locus.beg.mu_col = 0;
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
- MU_IOCTL_LOGSTREAM_SET_LOCUS, &locus);
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &locus);
mail_mainloop (source_readline, input, 0);
interactive = save_term;
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
- MU_IOCTL_LOGSTREAM_SET_LOCUS, NULL);
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, NULL);
mu_stream_unref (input);
return 0;
}
diff --git a/mh/.gitignore b/mh/.gitignore
index 4e2b87b..99f999a 100644
--- a/mh/.gitignore
+++ b/mh/.gitignore
@@ -14,8 +14,7 @@ forw
inc
install-mh
mark
-mh_alias.h
-mh_alias_gram.c
+mh_alias_gram.[ch]
mh_alias_lex.c
mh_fmtgram.c
mhl
diff --git a/mh/Makefile.am b/mh/Makefile.am
index 3107602..d4c89a8 100644
--- a/mh/Makefile.am
+++ b/mh/Makefile.am
@@ -68,33 +68,33 @@ noinst_LIBRARIES = libmh.a
libmh_a_SOURCES= \
compcommon.c\
mboxprop.c\
- mh_alias_gram.c\
- mh_alias_lex.c\
+ mh_alias_gram.y\
+ mh_alias_lex.l\
mh_getopt.c\
mh_global.c\
mh_format.c\
mh_init.c\
mh_list.c\
- mh_fmtgram.c\
+ mh_fmtgram.y\
mh_msgset.c\
mh_sequence.c\
mh_stream.c\
mh_whatnow.c\
mh_whom.c\
whatnowenv.c
-noinst_HEADERS = mh.h mh_alias.h mh_format.h mh_getopt.h
+noinst_HEADERS = mh.h mh_alias_gram.h mh_format.h mh_getopt.h
-BUILT_SOURCES= \
- mh_fmtgram.c \
- pick-gram.c \
- pick-gram.h \
- mh_alias_gram.c \
- mh_alias_lex.c \
- mh_alias.h
+BUILT_SOURCES=\
+ mh_fmtgram.c\
+ pick-gram.c\
+ pick-gram.h\
+ mh_alias_gram.c\
+ mh_alias_gram.h\
+ mh_alias_lex.c
MAINTAINERCLEANFILES=$(BUILT_SOURCES)
-EXTRA_DIST = mh_fmtgram.y pick.y mh_alias.y mh_alias.l
+EXTRA_DIST = gylwrap.conf
mhlibdir = $(pkgdatadir)/mh
@@ -119,9 +119,9 @@ mh_LIBS = \
@MU_COMMON_LIBRARIES@
LDADD = $(mh_LIBS)
scan_LDADD = $(mh_LIBS) @CURSES_LIBS@
-pick_SOURCES = pick.c pick.h pick-gram.c pick-gram.h
+pick_SOURCES = pick.c pick.h pick-gram.y pick-gram.h
-YLWRAP = $(SHELL) $(mu_aux_dir)/gylwrap
+YLWRAP = @MU_YLWRAP@
AM_YFLAGS=-vt
inc_LDADD = \
@@ -144,29 +144,6 @@ inc_LDADD = \
${MU_LIB_MAILUTILS}\
@MU_COMMON_LIBRARIES@
-
-pick-gram.c pick-gram.h: $(srcdir)/pick.y
- $(YLWRAP) "$(YACC) $(AM_YFLAGS) -d" $< \
- y.tab.c pick-gram.c y.tab.h pick-gram.h \
- y.output pick.output \
- -- -yy pick_yy
-
-mh_fmtgram.c: $(srcdir)/mh_fmtgram.y
- $(YLWRAP) "$(YACC) $(AM_YFLAGS)" $< \
- y.tab.c mh_fmtgram.c y.output fmtgram.y.output \
- -- -yy fmt_yy
-
-mh_alias_gram.c mh_alias.h: $(srcdir)/mh_alias.y
- $(YLWRAP) "$(YACC) $(AM_YFLAGS) -d" $< \
- y.tab.c mh_alias_gram.c y.tab.h mh_alias.h \
- y.output mh_alias.output \
- -- -yy ali_yy
-
-mh_alias_lex.c: $(srcdir)/mh_alias.l mh_alias.h
- $(YLWRAP) "$(LEX) $(AM_LEXFLAGS) $(LEXFLAGS)" \
- $(srcdir)/mh_alias.l lex.yy.c mh_alias_lex.c \
- -- -yy ali_yy
-
install-exec-hook:
@here=`pwd`; \
cd $(DESTDIR)$(bindir); \
diff --git a/mh/gylwrap.conf b/mh/gylwrap.conf
new file mode 100644
index 0000000..9954962
--- a/dev/null
+++ b/mh/gylwrap.conf
@@ -0,0 +1,13 @@
+# Configuration settings for gylwrap.
+# See ../mu-aux/gylwrap --help, for details.
+
+[pick-gram.y]
+ yyrepl = pick_yy
+ flags = -d
+[mh_fmtgram.y]
+ yyrepl = fmt_yy
+[mh_alias_gram.y]
+ yyrepl = ali_yy
+ flags = -d
+[mh_alias_lex.l]
+ yyrepl = ali_yy
diff --git a/mh/mh.h b/mh/mh.h
index 2a3cd88..76bc85e 100644
--- a/mh/mh.h
+++ b/mh/mh.h
@@ -385,7 +385,6 @@ const char *mh_seq_read (mu_mailbox_t mbox, const char *name, int flags);
void mh_comp_draft (const char *formfile, const char *draftfile);
int check_draft_disposition (struct mh_whatnow_env *wh, int use_draft);
-void ali_parse_error (const char *fmt, ...) MU_PRINTFLIKE(1,2);
void ali_verbatim (int enable);
char *mh_safe_make_file_name (const char *dir, const char *file);
diff --git a/mh/mh_alias.y b/mh/mh_alias_gram.y
index 54e3cd1..26b13ec 100644
--- a/mh/mh_alias.y
+++ b/mh/mh_alias_gram.y
@@ -20,6 +20,8 @@
#include <pwd.h>
#include <grp.h>
#include <sys/types.h>
+#include <mailutils/locus.h>
+#include <mailutils/yyloc.h>
struct mh_alias
{
@@ -31,7 +33,7 @@ struct mh_alias
static mu_list_t alias_list;
static mu_list_t
-list_create_or_die ()
+list_create_or_die (void)
{
int status;
mu_list_t list;
@@ -39,7 +41,7 @@ list_create_or_die ()
status = mu_list_create (&list);
if (status)
{
- ali_parse_error (_("can't create list: %s"), mu_strerror (status));
+ mu_error (_("can't create list: %s"), mu_strerror (status));
exit (1);
}
return list;
@@ -86,6 +88,17 @@ ali_list_to_string (mu_list_t *plist)
return string;
}
+static void
+ali_append (struct mh_alias *ali)
+{
+ if (ali)
+ {
+ if (!alias_list)
+ alias_list = list_create_or_die ();
+ mu_list_append (alias_list, ali);
+ }
+}
+
static mu_list_t unix_group_to_list (char *name);
static mu_list_t unix_gid_to_list (char *name);
static mu_list_t unix_passwd_to_list (void);
@@ -101,37 +114,34 @@ int yylex (void);
struct mh_alias *alias;
}
+%token EOL
%token <string> STRING
%type <list> address_list address_group string_list
%type <string> address
%type <alias> alias
+%locations
+
%%
-input : /* empty */
- | alias_list
- | alias_list nl
- | nl alias_list
- | nl alias_list nl
+input : alias_list
;
alias_list : alias
{
- if (!alias_list)
- alias_list = list_create_or_die ();
- mu_list_append (alias_list, $1);
+ ali_append ($1);
}
- | alias_list nl alias
+ | alias_list EOL alias
{
- mu_list_append (alias_list, $3);
+ ali_append ($3);
}
;
-nl : '\n'
- | nl '\n'
- ;
-
-alias : STRING ':' { ali_verbatim (1); } address_group
+alias : /* empty */
+ {
+ $$ = NULL;
+ }
+ | STRING ':' { ali_verbatim (1); } address_group
{
ali_verbatim (0);
$$ = mu_alloc (sizeof (*$$));
@@ -489,7 +499,7 @@ unix_passwd_to_list ()
}
int
-mh_read_aliases ()
+mh_read_aliases (void)
{
const char *p;
diff --git a/mh/mh_alias.l b/mh/mh_alias_lex.l
index 0deb7c9..371353e 100644
--- a/mh/mh_alias.l
+++ b/mh/mh_alias_lex.l
@@ -23,58 +23,23 @@
%{
#include <mh.h>
-#include <mh_alias.h>
+#include <mailutils/locus.h>
+#include <mailutils/yyloc.h>
+#include <mh_alias_gram.h>
#include <sys/stat.h>
#include <mailutils/cctype.h>
#include <mailutils/io.h>
-
-char *ali_filename;
-size_t ali_line_num;
-ino_t ali_source_inode;
-
-void
-va_ali_parse_error_loc (const char *name, size_t line,
- const char *fmt, va_list ap)
-{
- char *buf = NULL;
- size_t size = 0;
- mu_vasnprintf (&buf, &size, fmt, ap);
- if (name)
- mu_error ("%s:%lu: %s", name, (unsigned long) line, buf);
- else
- mu_error ("%s", buf);
- free (buf);
-}
-
-void
-ali_parse_error_loc (const char *name, size_t line, const char *fmt, ...)
-{
- va_list ap;
-
- va_start (ap, fmt);
- va_ali_parse_error_loc (name, line, fmt, ap);
- va_end (ap);
-}
-
-void
-ali_parse_error (const char *fmt, ...)
-{
- va_list ap;
-
- va_start (ap, fmt);
- va_ali_parse_error_loc (ali_filename, ali_line_num, fmt, ap);
- va_end (ap);
-}
+static mu_linetrack_t trk;
+static ino_t ali_source_inode;
int
yyerror (char *s)
{
- ali_parse_error ("%s", s);
+ mu_error ("%s", s);
return 0;
}
-#ifdef FLEX_SCANNER
#define xinput() (yyin ? getc(yyin) : EOF)
#undef YY_INPUT
#define YY_INPUT(buf,result,max_size) do { \
@@ -97,127 +62,20 @@ yyerror (char *s)
yy_switch_to_buffer(s); \
} while (0)
-#else
-/* AT&T Lex */
-
-static void lex_set_buffer (FILE *fp);
-static void lex_delete_buffer (LEX_BUFFER_STATE buf);
-static int xinput (void);
-static int xunput (void);
-
-#undef unput
-#define unput(c) xunput(c)
-#undef input
-#define input() xinput()
-
-#define LEX_BUF_SIZE 16384
-#define LEX_PUTBACK_SIZE 32
-
-typedef struct {
- FILE *yyin;
- char *buffer;
- size_t bufsize;
- size_t level;
- char *ptr;
- char *putback;
- size_t pb_size;
- size_t pb_level;
-} LEX_BUFFER_STATE;
-LEX_BUFFER_STATE current_buffer;
+#define YY_USER_ACTION \
+ do \
+ { \
+ mu_linetrack_advance (trk, &yylloc, yytext, yyleng); \
+ mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, \
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &yylloc); \
+ } \
+ while (0);
-#define SET_BUFFER_STATE(s) do { \
- (s) = current_buffer; \
- lex_set_buffer(yyin); \
-} while (0)
-#define RESTORE_BUFFER_STATE(s) do { \
- lex_delete_buffer(current_buffer); \
- current_buffer = (s); \
- yyin = current_buffer.yyin; \
-} while (0)
-
-void
-lex_set_buffer (FILE *fp)
-{
- char *buf;
- size_t size;
-
- for (size = LEX_BUF_SIZE; size > 1; size /= 2)
- if (buf = malloc (size))
- break;
-
- if (!buf)
- {
- ali_parse_error (_("not enough memory"));
- abort ();
- }
-
- current_buffer.yyin = yyin;
- current_buffer.buffer = buf;
- current_buffer.bufsize = size;
- current_buffer.level = 0;
- current_buffer.ptr = current_buffer.buffer;
- current_buffer.pb_size = current_buffer.pb_level = 0;
- current_buffer.putback = NULL;
-}
-
-void
-lex_delete_buffer (LEX_BUFFER_STATE buf)
-{
- free (buf.buffer);
- if (buf.putback)
- free (buf.putback);
-}
-
-int
-xinput ()
-{
- if (!yyin)
- return EOF;
-
- if (current_buffer.pb_level)
- return current_buffer.putback[--current_buffer.pb_level];
-
- if (current_buffer.level <= 0)
- {
- int n;
-
- if (feof (yyin))
- return 0;
- n = fread (current_buffer.buffer, 1,
- current_buffer.bufsize, yyin);
- if (n <= 0)
- return 0;
- current_buffer.level = n;
- current_buffer.ptr = current_buffer.buffer;
- }
- current_buffer.level--;
- return *current_buffer.ptr++;
-}
-
-int
-xunput (int c)
-{
- if (current_buffer.pb_level == current_buffer.pb_size)
- {
- char *putback;
- current_buffer.pb_size += LEX_PUTBACK_SIZE;
- putback = mu_alloc (current_buffer.pb_size);
- memcpy (putback, current_buffer.putback,
- current_buffer.pb_level);
- free (current_buffer.putback);
- current_buffer.putback = putback;
- }
- current_buffer.putback[current_buffer.pb_level++] = c;
- return c;
-}
-
-#endif
-
struct buffer_ctx {
struct buffer_ctx *prev;
- char *filename;
- int line;
+ mu_linetrack_t trk;
ino_t i_node;
+ struct mu_locus_range incl_range;
FILE *yyin;
int exec_p;
LEX_BUFFER_STATE state;
@@ -250,27 +108,26 @@ push_source (const char *name, int fail)
if (stat (filename, &st))
{
if (fail)
- ali_parse_error (_("can't stat `%s': %s"), filename, strerror (errno));
+ mu_error (_("can't stat `%s': %s"), filename, strerror (errno));
free (filename);
return 1;
}
- if (ali_filename && st.st_ino == ali_source_inode)
+ if (yylloc.beg.mu_file && st.st_ino == ali_source_inode)
{
- ali_parse_error (_("recursive inclusion"));
+ mu_error (_("recursive inclusion"));
free (filename);
return 1;
}
if ((ctx = ctx_lookup (st.st_ino)))
{
- ali_parse_error (_("recursive inclusion"));
+ mu_error (_("recursive inclusion"));
if (ctx->prev)
- ali_parse_error_loc (ctx->prev->filename, ctx->prev->line,
- _("`%s' already included here"),
- filename);
+ mu_diag_at_locus_range (MU_LOG_ERROR, &ctx->incl_range,
+ _("`%s' already included here"),
+ filename);
else
- ali_parse_error (_("`%s' already included at top level"),
- filename);
+ mu_error (_("`%s' already included at top level"), filename);
free (filename);
return 1;
}
@@ -278,7 +135,7 @@ push_source (const char *name, int fail)
fp = fopen (filename, "r");
if (!fp)
{
- ali_parse_error (_("can't open `%s': %s"), filename, strerror (errno));
+ mu_error (_("can't open `%s': %s"), filename, strerror (errno));
free (filename);
return 1;
}
@@ -295,8 +152,8 @@ push_source (const char *name, int fail)
fp = popen (filename, "r");
if (!fp)
{
- ali_parse_error (_("can't execute `%s': %s"),
- filename, strerror (errno));
+ mu_error (_("can't execute `%s': %s"),
+ filename, strerror (errno));
free (filename);
return 1;
}
@@ -306,12 +163,12 @@ push_source (const char *name, int fail)
}
/* Push current context */
- if (ali_filename)
+ if (yylloc.beg.mu_file)
{
ctx = mu_alloc (sizeof (*ctx));
- ctx->filename = ali_filename;
+ ctx->trk = trk;
+ mu_locus_range_copy (&ctx->incl_range, &yylloc);
ctx->exec_p = exec_p;
- ctx->line = ali_line_num;
ctx->i_node = ali_source_inode;
ctx->yyin = yyin;
ctx->prev = context_stack;
@@ -330,34 +187,30 @@ push_source (const char *name, int fail)
lex_set_buffer (yyin);
#endif
}
- ali_filename = filename;
- ali_line_num = 1;
+ MU_ASSERT (mu_linetrack_create (&trk, filename, 2));
+ free (filename);
ali_source_inode = st.st_ino;
exec_p = ex;
return 0;
}
static int
-pop_source ()
+pop_source (void)
{
struct buffer_ctx *ctx;
if (yyin)
(exec_p ? pclose : fclose) (yyin);
-#ifndef FLEX_SCANNER
- lex_delete_buffer (current_buffer);
-#endif
- if (ali_filename)
- free (ali_filename);
- ali_filename = NULL;
+ mu_linetrack_destroy (&trk);
if (!context_stack)
{
+ mu_locus_range_deinit (&yylloc);
yyin = NULL;
return 1;
}
+ mu_locus_range_deinit (&context_stack->incl_range);
/* Restore previous context */
- ali_filename = context_stack->filename;
- ali_line_num = context_stack->line + 1; /* < line did not increment it */
+ trk = context_stack->trk;
ali_source_inode = context_stack->i_node;
exec_p = context_stack->exec_p;
RESTORE_BUFFER_STATE (context_stack->state);
@@ -378,15 +231,15 @@ WORD [^ \t\n,:;<+=\*]+
SPEC [,:;+=\*]
%s VERBATIM
%%
-\\\n { ali_line_num++; }
-\n { ali_line_num++; return '\n';}
-^[ \t]*\;.*\n ali_line_num++;
+\\\n ;
+\n+ return EOL;
+^[ \t]*\;.*\n ;
^[ \t]*{WORD}\* { char *p;
for (p = yytext; p < yytext + yyleng; p++)
if (!mu_isspace (*p))
break;
yylval.string = mu_strdup (p);
- return STRING;}
+ return STRING; }
{WS} ;
{WORD} { yylval.string = mu_strdup (yytext); return STRING;}
^{WS}?"<"{WS}?{WORD} {
@@ -403,24 +256,22 @@ SPEC [,:;+=\*]
memcpy(yylval.string, yytext, yyleng);
yylval.string[yyleng] = 0;
return STRING;}
-. { char *p;
- mu_asprintf (&p,
- _("Stray character %03o in alias file"),
- yytext[0]);
- yyerror (p);
- free (p); }
+. { mu_error (_("Stray character %03o in alias file"),
+ yytext[0]); }
%%
int
-yywrap ()
+yywrap (void)
{
- return pop_source();
+ return pop_source ();
}
/* Parses the named alias file */
int
mh_alias_read (char const *name, int fail)
{
+ int rc;
+ int old_mode, mode;
extern int yydebug;
char *p = getenv ("ALI_YYDEBUG");
@@ -431,7 +282,16 @@ mh_alias_read (char const *name, int fail)
return 1;
if (yydebug)
fprintf (stderr, "Starting parse of %s\n", name);
- return yyparse ();
+
+ mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_GET_MODE, &old_mode);
+ mode = old_mode | MU_LOGMODE_LOCUS;
+ mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
+ rc = yyparse ();
+ mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_MODE, &old_mode);
+ return rc;
}
void
diff --git a/mh/pick.y b/mh/pick-gram.y
index ef2bdaa..ef2bdaa 100644
--- a/mh/pick.y
+++ b/mh/pick-gram.y
diff --git a/mh/tests/ali.at b/mh/tests/ali.at
index d18a910..28c0e54 100644
--- a/mh/tests/ali.at
+++ b/mh/tests/ali.at
@@ -70,8 +70,8 @@ exit $code
[0],
[gray, polak, admin
],
-[ali: mh_aliases2:2: recursive inclusion
-ali: mh_aliases2:2: `mh_aliases' already included at top level
+[ali: mh_aliases2:2.1-11: recursive inclusion
+ali: mh_aliases2:2.1-11: `mh_aliases' already included at top level
])
MH_CHECK([ali: group name],[ali04 ali-group-name],[
diff --git a/mimeview/.gitignore b/mimeview/.gitignore
index b18e41a..cee470e 100644
--- a/mimeview/.gitignore
+++ b/mimeview/.gitignore
@@ -3,11 +3,8 @@
.libs
Makefile
Makefile.in
-lex.yy.c
-mimetypes-decl.h
-mimetypes-gram.c
-mimetypes-lex.c
-mimetypes.output
+grammar.c
+grammar.h
+grammar.output
+lexer.c
mimeview
-y.output
-y.tab.c
diff --git a/mimeview/Makefile.am b/mimeview/Makefile.am
index 5334e40..039e2be 100644
--- a/mimeview/Makefile.am
+++ b/mimeview/Makefile.am
@@ -25,28 +25,15 @@ AM_CPPFLAGS = \
bin_PROGRAMS = mimeview
mimeview_SOURCES = \
mimeview.c \
- mimetypes-gram.c \
- mimetypes-lex.c \
- mimetypes-decl.h \
- mimeview.h
+ grammar.y \
+ lexer.l \
+ mimeview.h\
+ grammar.h
-YLWRAP = $(SHELL) $(mu_aux_dir)/gylwrap
-AM_YFLAGS=-vt
+YLWRAP = @MU_YLWRAP@
+AM_YFLAGS=-vtd
AM_LEXFLAGS=-d
-EXTRA_DIST = mimetypes.y mimetypes.l
-
-mimetypes-gram.c mimetypes-decl.h: $(srcdir)/mimetypes.y
- $(AM_V_GEN)$(YLWRAP) "$(YACC) $(AM_YFLAGS) -d" $< \
- y.tab.c mimetypes-gram.c y.tab.h mimetypes-decl.h \
- y.output mimetypes.output \
- -- -yy mimetypes_yy
-
-mimetypes-lex.c: $(srcdir)/mimetypes.l mimetypes-decl.h
- $(AM_V_GEN)$(YLWRAP) "$(LEX) $(AM_LEXFLAGS) $(LEXFLAGS)" \
- $(srcdir)/mimetypes.l lex.yy.c mimetypes-lex.c \
- -- -yy mimetypes_yy
-
-BUILT_SOURCES = mimetypes-gram.c mimetypes-lex.c mimetypes-decl.h
+EXTRA_DIST = gylwrap.conf
mimeview_LDADD = \
${MU_APP_LIBRARIES}\
diff --git a/mimeview/mimetypes.y b/mimeview/grammar.y
index cfb4fbe..cb36f39 100644
--- a/mimeview/mimetypes.y
+++ b/mimeview/grammar.y
@@ -22,7 +22,7 @@
#include <mailutils/cctype.h>
#include <mimeview.h>
-#include <mimetypes-decl.h>
+#include <grammar.h>
#include <regex.h>
static void
@@ -122,10 +122,11 @@ struct rule_tab
};
static mu_list_t rule_list;
+static size_t errors;
%}
%locations
-%expect 12
+%expect 15
%token <string> TYPE IDENT
%token <string> STRING
@@ -165,16 +166,21 @@ rule_line: /* empty */
p->type = $1.ptr;
p->node = $2;
p->priority = $3;
- p->loc.beg = @1.beg;
- p->loc.end = @3.end;
+ mu_locus_point_copy (&p->loc.beg, &@1.beg);
+ mu_locus_point_copy (&p->loc.end, &@3.end);
#if 0
YY_LOCATION_PRINT (stderr, p->loc);
fprintf (stderr, ": rule %s\n", p->type);
#endif
mu_list_append (rule_list, p);
}
+ | BOGUS
+ {
+ YYERROR;
+ }
| error
{
+ errors++;
if (arg_list)
mu_list_destroy (&arg_list);
arg_list = NULL;
@@ -228,6 +234,10 @@ stmt : '!' stmt
$$ = make_suffix_node (&$1, &@1);
}
| function
+ | BOGUS
+ {
+ YYERROR;
+ }
;
priority : PRIORITY '(' arglist ')'
@@ -280,6 +290,10 @@ arglist : arg
;
arg : STRING
+ | BOGUS
+ {
+ YYERROR;
+ }
;
%%
@@ -290,10 +304,10 @@ mimetypes_parse (const char *name)
int rc;
if (mimetypes_open (name))
return 1;
- yydebug = mu_debug_level_p (MU_DEBCAT_MIME, MU_DEBUG_TRACE3);
+ yydebug = mu_debug_level_p (MU_DEBCAT_APP, MU_DEBUG_TRACE3);
rc = yyparse ();
mimetypes_close ();
- return rc || rule_list == NULL;
+ return rc || errors;
}
static struct node *
@@ -301,7 +315,7 @@ make_node (enum node_type type, struct mu_locus_range const *loc)
{
struct node *p = mimetypes_malloc (sizeof *p);
p->type = type;
- p->loc = *loc;
+ mu_locus_range_copy (&p->loc, loc);
return p;
}
@@ -333,7 +347,7 @@ make_suffix_node (struct mimetypes_string *suffix,
node->v.suffix = *suffix;
return node;
}
-
+
struct builtin_tab
{
char *name;
@@ -759,7 +773,7 @@ check_suffix (char *suf)
void
mime_debug (int lev, struct mu_locus_range const *loc, char const *fmt, ...)
{
- if (mu_debug_level_p (MU_DEBCAT_MIME, lev))
+ if (mu_debug_level_p (MU_DEBCAT_APP, lev))
{
va_list ap;
diff --git a/mimeview/gylwrap.conf b/mimeview/gylwrap.conf
new file mode 100644
index 0000000..cd41ab2
--- a/dev/null
+++ b/mimeview/gylwrap.conf
@@ -0,0 +1,3 @@
+# Configuration settings for gylwrap.
+# See ../mu-aux/gylwrap --help, for details.
+yyrepl = mimetypes_yy
diff --git a/mimeview/mimetypes.l b/mimeview/lexer.l
index dd2311b..71de5d7 100644
--- a/mimeview/mimetypes.l
+++ b/mimeview/lexer.l
@@ -26,12 +26,12 @@
#include <stdio.h>
#include <sys/stat.h>
#include <mimeview.h>
-#include <mimetypes-decl.h>
+#include <grammar.h>
#include <mailutils/io.h>
-static struct mu_locus loc;
-static int newline;
-
+static mu_linetrack_t trk;
+struct mu_locus_point string_beg;
+
static mu_opool_t pool;
static unsigned
@@ -42,53 +42,24 @@ digit_to_number (char c)
c-'a'+10);
}
-static struct mu_locus prev_loc;
-static struct mu_locus string_beg;
-static int prev_newline;
-
static void
-advance_locus (void)
+drop_string (void)
{
- prev_loc = loc;
- prev_newline = newline;
-
- if (newline)
- {
- loc.mu_line++;
- loc.mu_col = 1;
- }
- yylloc.beg = loc;
- loc.mu_col += yyleng;
- yylloc.end = loc;
- yylloc.end.mu_col--;
-
-#if 0
- printf ("+%2d> %u:%u-%u:%u: %s\n",
- yyleng,
- yylloc.beg.mu_line, yylloc.beg.mu_col,
- yylloc.end.mu_line, yylloc.end.mu_col, yytext);
-#endif
- newline = yytext[yyleng-1] == '\n';
- mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
- MU_IOCTL_LOGSTREAM_SET_LOCUS, &loc);
+ mu_opool_clear (pool);
}
-
-static void
-retreat_locus (void)
-{
- loc = prev_loc;
- newline = prev_newline;
-}
-
+
static void
finish_string (void)
{
mu_opool_append_char (pool, 0);
yylval.string.ptr = mu_opool_finish (pool, &yylval.string.len);
yylval.string.len--;
- yylloc.end = yylloc.beg;
+
+ mu_locus_point_copy (&yylloc.end, &yylloc.beg);
yylloc.end.mu_col--;
- yylloc.beg = string_beg;
+ mu_locus_point_copy (&yylloc.beg, &string_beg);
+ mu_locus_point_deinit (&string_beg);
+
if (mu_debug_level_p (MU_DEBCAT_APP, MU_DEBUG_TRACE5))
{
size_t i;
@@ -106,7 +77,15 @@ finish_string (void)
#endif
}
-#define YY_USER_ACTION advance_locus ();
+#define YY_USER_ACTION \
+ do \
+ { \
+ mu_linetrack_advance (trk, &yylloc, yytext, yyleng); \
+ mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, \
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &yylloc); \
+ } \
+ while (0);
+
%}
%x RULE ARGS ASTRING
@@ -127,6 +106,11 @@ WS [ \t][ \t]*
BEGIN (RULE);
return TYPE;
}
+
+. {
+ mu_error (_("type/subtype is missing"));
+ return BOGUS;
+}
}
<RULE>{
@@ -174,12 +158,11 @@ WS [ \t][ \t]*
{WS} mu_error ("unexpected whitespace in argument list");
\n {
mu_error ("unexpected newline in argument list");
- BEGIN (RULE);
- return EOL;
+ return BOGUS;
}
. {
- string_beg = yylloc.beg;
- retreat_locus ();
+ mu_locus_point_copy (&string_beg, &yylloc.beg);
+ mu_linetrack_retreat (trk, 1);
yyless (0);
BEGIN (ASTRING);
}
@@ -217,8 +200,14 @@ WS [ \t][ \t]*
mu_opool_append (pool, yytext, yyleng);
}
-. {
- retreat_locus ();
+\n {
+ mu_error ("unexpected newline in argument");
+ drop_string ();
+ return BOGUS;
+}
+
+. {
+ mu_linetrack_retreat (trk, 1);
yyless (0);
BEGIN (ARGS);
finish_string ();
@@ -232,8 +221,9 @@ mimetypes_open (const char *name)
{
struct stat st;
int mode;
-
- yy_flex_debug = mu_debug_level_p (MU_DEBCAT_MIME, MU_DEBUG_TRACE4);
+ char *filename;
+
+ yy_flex_debug = mu_debug_level_p (MU_DEBCAT_APP, MU_DEBUG_TRACE4);
if (stat (name, &st))
{
@@ -242,28 +232,26 @@ mimetypes_open (const char *name)
}
if (S_ISDIR (st.st_mode))
- loc.mu_file = mu_make_file_name (name, "mime.types");
+ filename = mu_make_file_name (name, "mime.types");
else
- loc.mu_file = mu_strdup (name);
- loc.mu_line = 1;
- loc.mu_col = 1;
- newline = 0;
-
- yyin = fopen (loc.mu_file, "r");
+ filename = mu_strdup (name);
+
+ yyin = fopen (filename, "r");
if (!yyin)
{
- mu_error (_("cannot open `%s': %s"), loc.mu_file, mu_strerror (errno));
- free (loc.mu_file);
+ mu_error (_("cannot open `%s': %s"), filename, mu_strerror (errno));
+ free (filename);
return -1;
}
+ MU_ASSERT (mu_linetrack_create (&trk, filename, 3));
+ free (filename);
+
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_GET_MODE, &mode);
mode |= MU_LOGMODE_LOCUS;
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
- mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
- MU_IOCTL_LOGSTREAM_SET_LOCUS, &loc);
mu_opool_create (&pool, MU_OPOOL_ENOMEMABRT);
return 0;
@@ -275,16 +263,15 @@ mimetypes_close ()
int mode;
fclose (yyin);
- /* FIXME: Don't free (loc.mu_file), because it is referenced by
- mu_locus structures in the parse tree */
-
+ mu_locus_range_deinit (&yylloc);
+ mu_linetrack_destroy (&trk);
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_GET_MODE, &mode);
mode &= ~MU_LOGMODE_LOCUS;
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
- MU_IOCTL_LOGSTREAM_SET_LOCUS, NULL);
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, NULL);
}
int
@@ -319,49 +306,34 @@ mimetypes_malloc (size_t size)
void
lex_next_rule (void)
{
- int bol = 0;
int c;
-
- if (newline)
- {
- loc.mu_col = 0;
- loc.mu_line++;
- newline = 0;
- bol = 1;
- }
+ int dbg = yy_flex_debug
+ || mu_debug_level_p (MU_DEBCAT_APP, MU_DEBUG_TRACE6);
- if (yy_flex_debug)
+ if (dbg)
{
YY_LOCATION_PRINT (stderr, yylloc);
fprintf (stderr, ": started error recovery\n");
}
while ((c = input ()) != EOF)
{
- loc.mu_col++;
- if (c == '\n')
- {
- loc.mu_line++;
- loc.mu_col = 0;
- bol = 1;
- }
- else if (bol)
+ char ch = c;
+ if (!mu_isspace (c) && mu_linetrack_at_bol (trk))
{
- bol = 0;
- if (!(c == ' ' || c == '\t'))
- {
- unput (c);
- break;
- }
- }
+ unput (c);
+ break;
+ }
+ mu_linetrack_advance (trk, &yylloc, &ch, 1);
}
- if (yy_flex_debug)
+ if (dbg)
{
- yylloc.beg = yylloc.end = loc;
- YY_LOCATION_PRINT (stderr, yylloc);
+ struct mu_locus_range lr = MU_LOCUS_RANGE_INITIALIZER;
+ mu_linetrack_locus (trk, &lr.beg);
+ YY_LOCATION_PRINT (stderr, lr);
fprintf (stderr, ": finished error recovery\n");
+ mu_locus_point_deinit (&lr.beg);
}
BEGIN (RULE);
unput ('\n');
- loc.mu_col = 0;
- loc.mu_line--;
-}
+ mu_linetrack_retreat (trk, 1);
+ }
diff --git a/mimeview/mimeview.c b/mimeview/mimeview.c
index e67593d..e7194ac 100644
--- a/mimeview/mimeview.c
+++ b/mimeview/mimeview.c
@@ -66,7 +66,7 @@ cli_debug (struct mu_parseopt *po, struct mu_option *opt,
lev = MU_DEBUG_LEVEL_UPTO (MU_DEBUG_TRACE2);
else
{
- mu_debug_get_category_level (MU_DEBCAT_MIME, &lev);
+ mu_debug_get_category_level (MU_DEBCAT_APP, &lev);
for (; *arg; arg++)
{
switch (*arg)
@@ -88,7 +88,7 @@ cli_debug (struct mu_parseopt *po, struct mu_option *opt,
}
}
}
- mu_debug_set_category_level (MU_DEBCAT_MIME, lev);
+ mu_debug_set_category_level (MU_DEBCAT_APP, lev);
}
static void
@@ -222,11 +222,11 @@ display_file (const char *file, const char *type)
argv[5] = (char*) mimeview_file;
argv[6] = NULL;
- if (mu_debug_level_p (MU_DEBCAT_MIME, MU_DEBUG_TRACE0))
+ if (mu_debug_level_p (MU_DEBCAT_APP, MU_DEBUG_TRACE0))
{
char *string;
mu_argcv_string (6, argv, &string);
- mu_debug (MU_DEBCAT_MIME, MU_DEBUG_TRACE0,
+ mu_debug (MU_DEBCAT_APP, MU_DEBUG_TRACE0,
(_("executing %s...\n"), string));
free (string);
}
@@ -247,7 +247,7 @@ display_file (const char *file, const char *type)
{
display_stream_mailcap (mimeview_file, mimeview_stream, hdr,
no_ask_types, interactive, dry_run,
- MU_DEBCAT_MIME);
+ MU_DEBCAT_APP);
mu_header_destroy (&hdr);
}
}
@@ -264,9 +264,9 @@ main (int argc, char **argv)
if (dry_run)
{
mu_debug_level_t lev;
- mu_debug_get_category_level (MU_DEBCAT_MIME, &lev);
+ mu_debug_get_category_level (MU_DEBCAT_APP, &lev);
lev |= MU_DEBUG_LEVEL_UPTO (MU_DEBUG_TRACE2);
- mu_debug_set_category_level (MU_DEBCAT_MIME, lev);
+ mu_debug_set_category_level (MU_DEBCAT_APP, lev);
}
if (argc == 0 && !lint)
diff --git a/mimeview/mimeview.h b/mimeview/mimeview.h
index 39fb7f4..0f0d61f 100644
--- a/mimeview/mimeview.h
+++ b/mimeview/mimeview.h
@@ -22,6 +22,8 @@
# include <strings.h>
#endif
#include <mailutils/mailutils.h>
+#include <mailutils/locus.h>
+#include <mailutils/yyloc.h>
#include <fnmatch.h>
struct mimetypes_string
@@ -48,29 +50,3 @@ const char *get_file_type (void);
extern char const *mimeview_file;
extern mu_stream_t mimeview_stream;
-struct mu_locus_range
-{
- struct mu_locus beg;
- struct mu_locus end;
-};
-
-#define YYLTYPE struct mu_locus_range
-#define YYLLOC_DEFAULT(Current, Rhs, N) \
- do \
- { \
- if (N) \
- { \
- (Current).beg = YYRHSLOC(Rhs, 1).beg; \
- (Current).end = YYRHSLOC(Rhs, N).end; \
- } \
- else \
- { \
- (Current).beg = YYRHSLOC(Rhs, 0).end; \
- (Current).end = (Current).beg; \
- } \
- } while (0)
-#define YY_LOCATION_PRINT(File, Loc) \
- fprintf(File, "%s:%u.%u-%u.%u", \
- (Loc).beg.mu_file, \
- (Loc).beg.mu_line, (Loc).beg.mu_col, \
- (Loc).end.mu_line, (Loc).end.mu_col)
diff --git a/mimeview/tests/testsuite.at b/mimeview/tests/testsuite.at
index 971b1a2..05c7b87 100644
--- a/mimeview/tests/testsuite.at
+++ b/mimeview/tests/testsuite.at
@@ -40,8 +40,8 @@ $2: $4
m4_pushdef([build_expect],[__build_expect([],m4_shift(m4_shift($@)))])
-# MIMETEST(NAME,TYPES,FILE,CONTENT,RES)
-m4_pushdef([MIMETEST],[
+# MIMEIDENTIFY(NAME,TYPES,FILE,CONTENT,RES)
+m4_pushdef([MIMEIDENTIFY],[
AT_SETUP([$1])
AT_KEYWORDS([mimeview])
AT_CHECK([
@@ -55,17 +55,29 @@ mimeview MIMEVIEW_OPTIONS --identify -f mime.types select_args($@)
AT_CLEANUP
])
+m4_pushdef([MIMETEST],[
+AT_SETUP([$1])
+AT_KEYWORDS([mimeview])
+AT_CHECK([
+AT_DATA([mime.types],[$2
+])
+mimeview MIMEVIEW_OPTIONS --debug-level=app.=trace6 -t -f mime.types
+],
+m4_shift(m4_shift($@)))
+AT_CLEANUP
+])
+
dnl ------------------------------------------------------------
AT_INIT
AT_TESTED([mimeview])
MUT_VERSION([mimeview])
-MIMETEST([default],
+MIMEIDENTIFY([default],
[application/octet-stream],
[input], [], [application/octet-stream])
-MIMETEST([suffixes],
+MIMEIDENTIFY([suffixes],
[foo/x-bar bar baz
foo/x-qux qux quux
],
@@ -74,13 +86,13 @@ foo/x-qux qux quux
[a.quux], [], [foo/x-qux],
[a.qx], [], [unknown])
-MIMETEST([default ordering],
+MIMEIDENTIFY([default ordering],
[text/foo bar
text/bar bar
],
[a.bar], [], [text/bar])
-MIMETEST([priority],
+MIMEIDENTIFY([priority],
[text/bar bar
text/foo bar priority(20)
],
@@ -89,7 +101,7 @@ text/foo bar priority(20)
AT_BANNER([Functions])
# match("pattern") Pattern match on filename
-MIMETEST([match],
+MIMEIDENTIFY([match],
[application/x-csource match(*.c)
],
[a.c],[],[application/x-csource],
@@ -97,7 +109,7 @@ MIMETEST([match],
# ascii(offset,length) True if bytes are valid printable ASCII
# (CR, NL, TAB, BS, 32-126)
-MIMETEST([ascii],
+MIMEIDENTIFY([ascii],
[application/x-bar ascii(16,6)
],
[one],[-seek 16 -string foobar -int 100],[application/x-bar],
@@ -105,7 +117,7 @@ MIMETEST([ascii],
# printable(offset,length) True if bytes are printable 8-bit chars
# (CR, NL, TAB, BS, 32-126, 128-254)
-MIMETEST([printable],
+MIMEIDENTIFY([printable],
[application/x-bar printable(16,6)
],
[one],[-seek 16 -string foobar -int 100],[application/x-bar],
@@ -113,14 +125,14 @@ MIMETEST([printable],
[three],[-seek 16 -string fooba -byte 127],[unknown])
# regex(offset,"regex") True if bytes match regular expression
-MIMETEST([regex],
+MIMEIDENTIFY([regex],
[application/pdf regex(0,^[[\n\r]]*%PDF)
],
[one],[-byte 10 -byte 10 -byte 13 -byte 10 -string %PDF],[application/pdf],
[two],[-byte 10 -byte 10 -byte 13 -byte 7 -string %PDF],[unknown])
# string(offset,"string") True if bytes are identical to string
-MIMETEST([string],
+MIMEIDENTIFY([string],
[application/x-foo string(5,FOO)
],
[one],[-seek 5 -string FOO],[application/x-foo],
@@ -128,28 +140,28 @@ MIMETEST([string],
# istring(offset,"string") True if bytes are identical to
# case-insensitive string
-MIMETEST([istring],
+MIMEIDENTIFY([istring],
[application/x-foo istring(5,FOO)
],
[one],[-seek 5 -string foO],[application/x-foo],
[two],[-seek 4 -string FOO],[unknown])
# char(offset,value) True if byte is identical
-MIMETEST([char],
+MIMEIDENTIFY([char],
[application/x-foo char(5,15)
],
[one],[-seek 5 -byte 15],[application/x-foo],
[two],[-seek 5 -byte 1],[unknown])
# short(offset,value) True if 16-bit integer is identical
-MIMETEST([short],
+MIMEIDENTIFY([short],
[application/x-foo short(5,1600)
],
[one],[-seek 5 -short 1600],[application/x-foo],
[two],[-seek 5 -short 1601],[unknown])
# int(offset,value) True if 32-bit integer is identical
-MIMETEST([int],
+MIMEIDENTIFY([int],
[application/x-foo int(5,16578)
],
[one],[-seek 5 -int 16578],[application/x-foo],
@@ -159,13 +171,13 @@ MIMETEST([int],
# FIXME
# contains(offset,range,"string") True if the range contains the string
-MIMETEST([contains],
+MIMEIDENTIFY([contains],
[application/x-foo contains(10,1024,"TESTSTRING")
],
[one],[-seek 512 -string TESTSTRING],[application/x-foo],
[two],[-seek 512 -string TEST],[unknown])
-MIMETEST([argument strings],
+MIMEIDENTIFY([argument strings],
[application/x-foo string(0,"FOO")
application/x-bar string(0,'B A R')
application/x-baz string(0,"B A"Z<1B0103>BAZ)
@@ -176,7 +188,7 @@ application/x-qux string(0,<1B>45" Q "<01>)
[three],[-string "B AZ" -byte 0x1b -byte 0x01 -byte 0x03 -string BAZ],[application/x-baz],
[four],[-byte 0x1b -string '45 Q ' -byte 0x01],[application/x-qux])
-MIMETEST([logical or],
+MIMEIDENTIFY([logical or],
[text/x-bar bar baz string(0,bar) printable(3,10)
],
[one.bar],[],[text/x-bar],
@@ -185,16 +197,53 @@ MIMETEST([logical or],
[bar],[-seek 3 -string teststring],[text/x-bar],
[baz],[-seek 3 -string test -byte 0 -string tring],[unknown])
-MIMETEST([logical and],
+MIMEIDENTIFY([logical and],
[text/x-foo bar + string(0,bar<10>) + printable(4,10)
],
[one.bar],[-string bar -byte 0x10 -string TESTSTRING],[text/x-foo],
[one],[-string bar -byte 0x10 -string TESTSTRING],[unknown],
[two.bar],[-string bar -byte 0x13 -byte 0x10 -string TEST],[unknown])
-MIMETEST([grouping],
+MIMEIDENTIFY([grouping],
[text/x-foo bar (string(0,bar) + printable(4,10))
],
[one.bar],[-string foo],[text/x-foo],
[two.baz],[-string bar -byte 0x10 -string TESTSTRING],[text/x-foo],
[three],[-string bar -byte 0x13 -byte 0x10 -string TESTSTRING],[unknown])
+
+MIMETEST([error recovery],
+[text/x-foo bar (string(0,bar) + printable(4,10))
+ string(10,baz)
+application/x-baz
+],
+[1],
+[],
+[mimeview: mime.types:2.1: type/subtype is missing
+mime.types:2.1: started error recovery
+mime.types:3: finished error recovery
+])
+
+MIMETEST([multiple error recovery],
+[text/x-foo bar (string(0,bar) + printable(4,10))
+ string(10,baz)
+application/x-baz baz
+image/jpeg jpeg jpg jpe string(0,<FFD8FF>) &&\
+ (char(3,0xe0) char(3,0xe1) char(3,0xe2) char(3,0xe3)\
+ char(3,0xe4) char(3,0xe5) char(3,0xe6) char(3,0xe7)
+ char(3,0xe8) char(3,0xe9) char(3,0xea) char(3,0xeb)\
+ char(3,0xec) char(3,0xed) char(3,0xee) char(3,0xef))
+image/tiff tiff tif string(0,MM<002A>) string(0,II<2A00>)
+],
+[1],
+[],
+[mimeview: mime.types:2.1: type/subtype is missing
+mime.types:2.1: started error recovery
+mime.types:3: finished error recovery
+mimeview: mime.types:6.63: syntax error
+mime.types:6.63: started error recovery
+mime.types:9: finished error recovery
+])
+
+
+m4_popdef([MIMETEST])
+m4_popdef([MIMEIDENTIFY]) \ No newline at end of file
diff --git a/mu-aux/gencl b/mu-aux/gencl
index 6e7ca58..4373bfd 100755
--- a/mu-aux/gencl
+++ b/mu-aux/gencl
@@ -2,6 +2,22 @@ eval '(exit $?0)' && eval 'exec perl -wS "$0" "$@"'
& eval 'exec perl -wS "$0" $argv:q'
if 0;
+# This file is part of GNU Mailutils.
+# 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/>.
+
use strict;
use POSIX qw(strftime);
use Getopt::Long qw(:config gnu_getopt no_ignore_case);
@@ -589,3 +605,7 @@ EOT
$fd = select($fd);
close $fd;
}
+
+# Local Variables:
+# mode: perl
+# End:
diff --git a/mu-aux/gitinfo b/mu-aux/gitinfo
index a932f2a..a830ff3 100755
--- a/mu-aux/gitinfo
+++ b/mu-aux/gitinfo
@@ -522,3 +522,6 @@ if (ref($format) eq 'CODE') {
print eval_format($format);
}
+# Local Variables:
+# mode: perl
+# End:
diff --git a/mu-aux/gylwrap b/mu-aux/gylwrap
index c91ab48..7dc0cc4 100755
--- a/mu-aux/gylwrap
+++ b/mu-aux/gylwrap
@@ -1,184 +1,357 @@
-#! /bin/sh
-# ylwrap - wrapper for lex/yacc invocations.
-# Copyright 1996-1999, 2007, 2010-2012, 2014-2017 Free Software
-# Foundation, Inc.
-# Written by Tom Tromey <tromey@cygnus.com>.
+eval '(exit $?0)' && eval 'exec perl -wS "$0" "$@"'
+ & eval 'exec perl -wS "$0" $argv:q'
+ if 0;
+
+# This file is part of GNU Mailutils.
+# Copyright (C) 2017 Free Software Foundation, Inc.
#
-# This program 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 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.
#
-# This program 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.
+# 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 this program. If not, see <http://www.gnu.org/licenses/>.
-
-# Usage:
-# ylwrap PROGRAM [ARGS] INPUT [OUTPUT DESIRED]... -- [-yy repl] [ARGS]...
-# * PROGRAM is program to run; options can follow but must start with `-'.
-# * INPUT is the input file
-# * OUTPUT is file PROG generates
-# * DESIRED is file we actually want
-# * ARGS are passed to PROG
-# * Optional -yy introduces the sequence to replace yy prefixes with.
-# Any number of OUTPUT,DESIRED pairs may be used.
-
-# The program to run.
-prog="$1"
-shift
-# Make any relative path in $prog absolute.
-case "$prog" in
- /* | [A-Za-z]:*) ;;
- */*) prog="`pwd`/$prog" ;;
-esac
-
-# We also have to accept options here and append them to the program.
-# Why? Suppose YACC is set to `bison -y'. Clearly nobody uses
-# ylwrap, or this would have been discovered earlier!
-while :; do
- case "$1" in
- -*)
- prog="$prog $1"
- shift
- ;;
- *)
- break
- ;;
- esac
-done
-
-# The input.
-input="$1"
-shift
-case "$input" in
- /* | [A-Za-z]:*)
- # Absolute path; do nothing.
- ;;
- *)
- # Relative path. Make it absolute.
- input="`pwd`/$input"
- ;;
-esac
-
-# The directory holding the input.
-input_dir="`echo $input | sed -e 's,/[^/]*$,,'`"
-# Quote $INPUT_DIR so we can use it in a regexp.
-# FIXME: really we should care about more than `.'.
-input_rx="`echo $input_dir | sed -e 's,\.,\\\.,g'`"
-
-pairlist=
-defout=$1
-while test "$#" -ne 0; do
- if test "$1" = "--"; then
- shift
- break
- fi
- pairlist="$pairlist $1"
- shift
-done
-
-STDOUT=""
-if [ $# -ne 0 ]; then
- while test "$#" -ne 0; do
- case "x$1" in
- x-yy)
- shift
- if [ $# -eq 0 ]; then
- echo "ylwrap: -yy requires an argument"
- exit 1
- fi
- YYREPL=$1
- shift;;
- x-stdout)
- shift
- STDOUT=$defout
- ;;
- *)
- break;;
- esac
- done
-fi
-
-# FIXME: add hostname here for parallel makes that run commands on
-# other machines. But that might take us over the 14-char limit.
-dirname=ylwrap$$
-trap "cd `pwd`; rm -rf $dirname > /dev/null 2>&1" 1 2 3 15
-mkdir $dirname || exit 1
-
-cd $dirname
-
-if [ -n "$STDOUT" ]; then
- $prog ${1+"$@"} "$input" > $STDOUT
-else
- $prog ${1+"$@"} "$input"
-fi
-status=$?
-
-if test $status -eq 0; then
- set X $pairlist
- shift
- first=yes
- # Since DOS filename conventions don't allow two dots,
- # the DOS version of Bison writes out y_tab.c instead of y.tab.c
- # and y_tab.h instead of y.tab.h. Test to see if this is the case.
- y_tab_nodot="no"
- if test -f y_tab.c || test -f y_tab.h; then
- y_tab_nodot="yes"
- fi
-
- while test "$#" -ne 0; do
- from="$1"
- # Handle y_tab.c and y_tab.h output by DOS
- if test $y_tab_nodot = "yes"; then
- if test $from = "y.tab.c"; then
- from="y_tab.c"
- else
- if test $from = "y.tab.h"; then
- from="y_tab.h"
- fi
- fi
- fi
- if test -f "$from"; then
- # If $2 is an absolute path name, then just use that,
- # otherwise prepend `../'.
- case "$2" in
- /* | [A-Za-z]:*) target="$2";;
- *) target="../$2";;
- esac
-
- # Edit out `#line' or `#' directives. We don't want the
- # resulting debug information to point at an absolute srcdir;
- # it is better for it to just mention the .y file with no
- # path.
- T=`basename $target`
- EXPR="/^#/ s,$input_rx/,,;s,\"$from\",\"$T\","
- if [ ! -z "$YYREPL" ]; then
- EXPR="$EXPR;s/yy/$YYREPL/g"
- fi
- sed -e "$EXPR" "$from" > "$target" || status=$?
- else
- # A missing file is only an error for the first file. This
- # is a blatant hack to let us support using "yacc -d". If -d
- # is not specified, we don't want an error when the header
- # file is "missing".
- if test $first = yes; then
- status=1
- fi
- fi
- shift
- shift
- first=no
- done
-else
- status=$?
-fi
-
-# Remove the directory.
-cd ..
-rm -rf $dirname
-
-exit $status
+# along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
+
+use strict;
+use warnings;
+use Getopt::Long qw(:config gnu_getopt no_ignore_case require_order auto_version);
+use File::Basename;
+use File::Temp qw(tempdir);
+use Pod::Man;
+use Pod::Usage;
+use Cwd 'abs_path';
+use List::Regexp;
+
+=head1 NAME
+
+gylwrap - wrapper for yacc, lex and similar programs
+
+=head1 SYNOPSIS
+
+B<gylwrap>
+[B<-?>]
+[B<--yyrepl=>I<PREFIX>]
+[B<--yysym=>I<STRING>]
+[B<--help>]
+[B<--version>]
+I<INPUT>
+[I<OUTPUT> I<DESIRED>]...
+B<--> I<PROGRAM> [I<ARGS>]
+
+=head1 DESCRIPTION
+
+Wraps B<lex> and B<yacc> invocations to rename their output files.
+It also ensures that multiple I<COMMAND> instances can be invoked
+in a single directory in parallel and allows for renaming global
+symbols to avoid clashes when multiple parsers and/or lexers are
+linked in a single executable.
+
+To achieve this, B<gylwrap> creates a temporary directory, changes
+to it, and runs I<PROGRAM>, with I<ARGS> and I<INPUT> as its arguments.
+Upon successful exit from I<PROGRAM>, B<gylwrap> processes the
+I<OUTPUT>-I<DESIRED> pairs. Each I<OUTPUT> file is then renamed
+to the file I<DESIRED>, taking care to fix up any eventual B<#line>
+directives.
+
+If B<--yyrepl=I<PREFIX>> is given, the global symbols that can cause
+name clashes are renamed by replacing the initial B<yy> with I<PREFIX>.
+For a list of symbols that are subject for replacement, inspect the
+B<@sym> variable at the start of the script. Additional names can be
+added to this list using the B<--yysym> option.
+
+Prior to running the I<PROGRAM>, B<gylwrap> program checks whether the
+file named B<gylwrap.conf> exists in directory of the I<INPUT> file.
+If found, it is parsed as follows. Empty lines and comments (introduced
+by the hash sign) are ignored. Rest of lines are either option
+assignements, or section headings.
+
+Option assignements have the form B<I<OPTION> = I<VALUE>>, and generally,
+have the same meaning as the corresponding command line option without
+the leading two dashes:
+
+=over 4
+
+=item B<yyrepl => I<PREFIX>
+
+Replace the B<yy> prefix with I<PREFIX> in the identifiers.
+
+=item B<yysym => I<NAME>
+
+Add I<NAME> to the list of symbols suitable for prefix replacement.
+This keyword can appear multiple times.
+
+=item B<flags => I<STRING>
+
+Add I<STRING> to the invocation of I<COMMAND>. This is useful, if you
+have several parsers in the same directory, and some of them require
+the B<-d> option, while others don't.
+
+=back
+
+Section headers have the form B<[I<FILE>]>. The settings under a
+section header have effect only if I<FILE> is the same as the I<INPUT>
+command line argument.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<--yyrepl=>I<PREFIX>
+
+Replace the B<yy> prefix in global symbols with I<PREFIX>.
+
+=item B<--yysym=>I<SYMBOL>
+
+Add I<SYMBOL> to the list of symbols subject for replacement.
+
+=item B<-?>, B<--help>
+
+Displays help text and exit
+
+=item B<--version>
+
+Displays program version and exits.
+
+=back
+
+=head1 NOTE
+
+This script is an improved version of the B<ylwrap> script, included
+in the GNU Automake distribution.
+
+=cut
+
+# List of symbols suitable for prefix replacements. See the
+# options --yyrepl and --yysym, and similar statements in the configuration
+# file.
+my @yysym = qw(
+ yymaxdepth
+ yyparse
+ yylex
+ yyerror
+ yylval
+ yychar
+ yydebug
+ yypact
+ yyr1
+ yyr2
+ yydef
+ yychk
+ yypgo
+ yyact
+ yyexca
+ yyerrflag
+ yynerrs
+ yyps
+ yypv
+ yys
+ yy_yys
+ yystate
+ yytmp
+ yyv
+ yy_yyv
+ yyval
+ yylloc
+ yyreds
+ yytoks
+ yylhs
+ yylen
+ yydefred
+ yydgoto
+ yysindex
+ yyrindex
+ yygindex
+ yytable
+ yycheck
+ yyname
+ yyrule
+
+ yy_create_buffer
+ yy_delete_buffer
+ yy_flex_debug
+ yy_init_buffer
+ yy_flush_buffer
+ yy_load_buffer_state
+ yy_switch_to_buffer
+ yyin
+ yyleng
+ yylex
+ yylineno
+ yyout
+ yyrestart
+ yytext
+ yywrap
+ yyalloc
+ yyrealloc
+ yyfree
+);
+
+our $VERSION = '1.00';
+
+# If prefix replacement is requested, the list above is assembled into
+# a single regular expression, stored here.
+my $yyrx;
+
+# String to replace the "yy" prefix with.
+my $yyrepl;
+
+# Input directory with special characters escaped, for "#line" directive
+# fixup.
+my $input_rx;
+
+# Configuration settings from the "gylwrap.conf" file. Indexed by
+# input file name. Default entry is ''.
+my %config;
+
+# Name of the first output file. This is used to avoid bailing out if
+# one of the output files (except the principal one) does not exist.
+my $parser;
+
+# Name this program was invoked as.
+my $progname = basename($0);
+
+# List of files created during the run, for cleanup purposes.
+my @created;
+
+sub filter {
+ my ($from, $to) = @_;
+ my $target = basename($to);
+ my $ifd;
+ unless (open($ifd, '<', $from)) {
+ return if $from ne $parser;
+ die "can't open input file $from: $!";
+ }
+ open(my $ofd, '>', $to)
+ or die "can't open output file $to: $!";
+ push @created, $to;
+ while (<$ifd>) {
+ if (/^#/) {
+ s{$input_rx/}{};
+ s{"$from"}{"$target"};
+ }
+ if ($yyrx) {
+ s{\byy($yyrx)\b}{${yyrepl}$1}g;
+ }
+ print $ofd $_
+ }
+ close $ifd;
+ close $ofd;
+}
+
+sub readconf {
+ my $file = shift;
+ open(my $fd, '<', $file)
+ or die "can't open $file: $!";
+ my $key = '';
+ while (<$fd>) {
+ chomp;
+ s/^\s+//;
+ if (/^#/ || /^$/) {
+ next;
+ } elsif (/^\[(.+)\]/) {
+ $key = $1;
+ } elsif (m/(.+?)\s*=\s*(.+)$/) {
+ if ($1 eq 'yysym' || $1 eq 'flags') {
+ push @{$config{$key}{$1}}, (split /\s+/, $2);
+ } else {
+ $config{$key}{$1} = $2;
+ }
+ } else {
+ print STDERR "$file:$.: unrecognized line\n";
+ }
+ }
+ close($fd);
+}
+
+my $input;
+my @output;
+
+GetOptions("yyrepl=s" => \$yyrepl,
+ "yysym=s@" => \@yysym,
+ "help|?" => sub {
+ pod2usage(-exitstatus => 0, -verbose => 2);
+ }
+ ) or exit(1);
+
+$input = shift @ARGV;
+while (my $arg = shift @ARGV) {
+ last if ($arg eq '--');
+ push @output, $arg;
+}
+
+pod2usage(-exitstatus => 1, -verbose => 0, -output => \*STDERR)
+ unless (@output && (@output % 2) == 0);
+
+# Make sure input file name is absolute
+$input = abs_path($input);
+
+my $input_dir = dirname($input);
+$input_rx = qr($input_dir);
+
+my $confile = "$input_dir/gylwrap.conf";
+readconf($confile) if -r $confile;
+
+my $input_base = basename($input);
+unless ($yyrepl) {
+ $yyrepl = $config{$input_base}{yyrepl} || $config{''}{yyrepl};
+}
+if ($yyrepl) {
+ push @yysym, @{$config{$input_base}{yysym}}
+ if exists $config{$input_base}{yysym};
+ push @yysym, @{$config{''}{yysym}}
+ if exists $config{''}{yysym};
+ if ($yyrepl) {
+ $yyrx = regexp_opt({ type => 'pcre' }, map { s/^yy//; $_ } @yysym);
+ }
+}
+
+if (my $flags = $config{$input_base}{flags} || $config{''}{flags}) {
+ push @ARGV, @$flags;
+}
+push @ARGV, $input;
+
+$parser = $output[0];
+
+# Create working directory
+my $wd = tempdir("ylXXXXXX", DIR => '.', CLEANUP => 1)
+ or die "cannot create temporary directory";
+chdir $wd
+ or die "cannot change to the temporary directory";
+END {
+ if ($?) {
+ unlink @created;
+ }
+ chdir "..";
+}
+
+system(@ARGV);
+if ($? == -1) {
+ print STDERR "$ARGV[0]: $!\n";
+ exit(127);
+} elsif ($? & 127) {
+ print STDERR "$ARGV[0] died with signal ".($? & 127)."\n";
+ exit(127);
+} else {
+ my $code = $? >> 8;
+ exit($code) if $code;
+}
+
+while (my $from = shift @output) {
+ my $to = shift @output;
+ $to = '../' . $to unless $to =~ m{^/};
+ filter($from, $to);
+}
+
+exit 0;
+
+# Local Variables:
+# mode: perl
+# End:
+
+
diff --git a/mu/libexec/dbm.c b/mu/libexec/dbm.c
index 50fe4ec..32d66c9 100644
--- a/mu/libexec/dbm.c
+++ b/mu/libexec/dbm.c
@@ -260,15 +260,17 @@ input_getline (struct iobuf *inp)
inp->length = mu_rtrim_class (inp->buffer, MU_CTYPE_ENDLN);
if (inp->buffer[0] == '#' && !is_dbm_directive (inp))
{
- struct mu_locus loc;
+ struct mu_locus_range loc;
mu_stream_ioctl (mu_strerr,
- MU_IOCTL_LOGSTREAM, MU_IOCTL_LOGSTREAM_GET_LOCUS,
+ MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_GET_LOCUS_RANGE,
&loc);
- loc.mu_line = strtoul (inp->buffer + 1, NULL, 10);
+ loc.beg.mu_line = strtoul (inp->buffer + 1, NULL, 10);
mu_stream_ioctl (mu_strerr,
- MU_IOCTL_LOGSTREAM, MU_IOCTL_LOGSTREAM_SET_LOCUS,
+ MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE,
&loc);
- free (loc.mu_file);
+ mu_locus_range_deinit (&loc);
continue;
}
break;
@@ -1322,7 +1324,8 @@ add_records (int mode, int replace)
const char *flt_argv[] = { "inline-comment", "#", "-S", "-i", "#", NULL };
int rc;
int save_log_mode = 0, log_mode;
- struct mu_locus save_locus = { NULL, }, locus;
+ struct mu_locus_range save_locus = MU_LOCUS_RANGE_INITIALIZER,
+ locus = MU_LOCUS_RANGE_INITIALIZER;
struct mu_dbm_datum key, contents;
struct iobuf input;
struct mu_wordsplit ws;
@@ -1364,18 +1367,21 @@ add_records (int mode, int replace)
/* Configure error stream to output input file location before each error
message */
- locus.mu_file = input_file ? input_file : "<stdin>";
- locus.mu_line = 0;
- locus.mu_col = 0;
+ locus.beg.mu_file = input_file ? input_file : "<stdin>";
+ locus.beg.mu_line = 0;
+ locus.beg.mu_col = 0;
+ memset (&locus.end, 0, sizeof locus.end);
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, MU_IOCTL_LOGSTREAM_GET_MODE,
&save_log_mode);
- mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, MU_IOCTL_LOGSTREAM_GET_LOCUS,
+ mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_GET_LOCUS_RANGE,
&save_locus);
log_mode = save_log_mode | MU_LOGMODE_LOCUS;
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, MU_IOCTL_LOGSTREAM_SET_MODE,
&log_mode);
- mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, MU_IOCTL_LOGSTREAM_SET_LOCUS,
+ mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE,
&locus);
/* Initialize I/O data */
@@ -1443,7 +1449,8 @@ add_records (int mode, int replace)
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, MU_IOCTL_LOGSTREAM_SET_MODE,
&save_log_mode);
- mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, MU_IOCTL_LOGSTREAM_SET_LOCUS,
+ mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE,
&save_locus);
if (known_meta_data)
diff --git a/mu/libexec/logger.c b/mu/libexec/logger.c
index d40f7d9..daa85a9 100644
--- a/mu/libexec/logger.c
+++ b/mu/libexec/logger.c
@@ -26,7 +26,7 @@ static char logger_args_doc[] = N_("[TEXT]");
static char *input_file = NULL;
static int logger_type = MU_STRERR_STDERR;
static int log_severity = MU_LOG_ERROR;
-static struct mu_locus locus;
+static struct mu_locus_range locus = MU_LOCUS_RANGE_INITIALIZER;
static int syslog_facility = LOG_USER;
static int syslog_priority = LOG_ERR;
static char *syslog_tag = NULL;
@@ -83,32 +83,67 @@ set_severity (struct mu_parseopt *po, struct mu_option *opt,
}
static void
-set_locus (struct mu_parseopt *po, struct mu_option *opt,
- char const *arg)
+parse_locus_point (char **ptr, struct mu_locus_point *pt,
+ struct mu_parseopt *po)
{
+ char *str = *ptr;
char *s;
-
- locus.mu_file = mu_strdup (arg);
- s = strchr (arg, ':');
+
+ s = strchr (str, ':');
if (s)
{
+ char *end;
*s++ = 0;
- locus.mu_line = strtoul (s, &s, 10);
- if (*s == ':')
+ if (*str)
+ mu_locus_point_set_file (pt, str);
+ pt->mu_line = strtoul (s, &end, 10);
+ if (end == s)
+ {
+ mu_parseopt_error (po, _("bad line number: %s"), s);
+ exit (po->po_exit_error);
+ }
+ s = end;
+ if (*s == '.' || *s == ':')
{
- locus.mu_col = strtoul (s + 1, &s, 10);
- if (*s)
+ s++;
+ pt->mu_col = strtoul (s, &end, 10);
+ if (end == s)
{
- mu_parseopt_error (po, _("bad column number: %s"), arg);
+ mu_parseopt_error (po, _("bad column number: %s"), s);
exit (po->po_exit_error);
}
- }
- else if (*s)
- {
- mu_parseopt_error (po, _("bad line number: %s"), arg);
- exit (po->po_exit_error);
+ s = end;
}
}
+ else
+ {
+ mu_parseopt_error (po, _("missing line number after %s"), s);
+ exit (po->po_exit_error);
+ }
+ *ptr = s;
+}
+
+static void
+set_locus (struct mu_parseopt *po, struct mu_option *opt,
+ char const *arg)
+{
+ char *s;
+ char *tmp;
+
+ tmp = mu_strdup (arg);
+ s = tmp;
+ parse_locus_point (&s, &locus.beg, po);
+ if (*s == '-')
+ {
+ mu_locus_point_set_file (&locus.end, locus.beg.mu_file);
+ locus.end.mu_line = locus.beg.mu_line;
+ locus.end.mu_col = locus.end.mu_col;
+ s++;
+ parse_locus_point (&s, &locus.end, po);
+ }
+
+ if (*s)
+ mu_parseopt_error (po, _("locus format error near %s"), s);
}
static struct mu_option logger_options[] = {
@@ -127,7 +162,7 @@ static struct mu_option logger_options[] = {
{ "severity", 's', N_("SEV"), MU_OPTION_DEFAULT,
N_("log at Mailutils severity level SEV"),
mu_c_string, NULL, set_severity },
- { "locus", 'l', N_("FILE:LINE[:COL]"), MU_OPTION_DEFAULT,
+ { "locus", 'l', N_("FILE:LINE[.COL][-FILE:LINE[.COL]]"), MU_OPTION_DEFAULT,
N_("set locus for logging"),
mu_c_string, NULL, set_locus },
{ "tag", 't', N_("TAG"), MU_OPTION_DEFAULT,
@@ -166,9 +201,9 @@ main (int argc, char **argv)
mode = MU_LOGMODE_SEVERITY | MU_LOGMODE_LOCUS;
mu_stream_ioctl (logger, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
- if (locus.mu_file)
+ if (locus.beg.mu_file)
mu_stream_ioctl (logger, MU_IOCTL_LOGSTREAM,
- MU_IOCTL_LOGSTREAM_SET_LOCUS, &locus);
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &locus);
mu_stream_ioctl (logger, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_SET_SEVERITY, &log_severity);
diff --git a/mu/libexec/wicket.c b/mu/libexec/wicket.c
index a9d586a..422d2f3 100644
--- a/mu/libexec/wicket.c
+++ b/mu/libexec/wicket.c
@@ -52,7 +52,7 @@ wicket_match (mu_stream_t stream, const char *str)
{
int rc, ret;
mu_url_t u, url;
- struct mu_locus loc;
+ struct mu_locus_point loc;
int flags = MU_URL_PARSE_ALL;
if (wicket_verbose > 2)
diff --git a/po/POTFILES.in b/po/POTFILES.in
index d3c413c..11e993c 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -43,8 +43,8 @@ libmu_sieve/prog.c
libmu_sieve/relational.c
libmu_sieve/require.c
libmu_sieve/runtime.c
-libmu_sieve/sieve.l
-libmu_sieve/sieve.y
+libmu_sieve/sieve-lex.l
+libmu_sieve/sieve-gram.y
libmu_sieve/tests.c
libmu_sieve/util.c
libmu_sieve/variables.c
@@ -174,8 +174,8 @@ mh/send.c
mh/whatnow.c
mh/whom.c
-mimeview/mimetypes.l
-mimeview/mimetypes.y
+mimeview/lexer.l
+mimeview/grammar.y
mimeview/mimeview.c
movemail/movemail.c
diff --git a/sieve/sieve.c b/sieve/sieve.c
index a87b261..6d718e0 100644
--- a/sieve/sieve.c
+++ b/sieve/sieve.c
@@ -495,8 +495,13 @@ main (int argc, char *argv[])
mu_sieve_set_logger (mach, _sieve_action_log);
if (expression_option)
- rc = mu_sieve_compile_buffer (mach, script, strlen (script),
- "stdin", 1);
+ {
+ struct mu_locus_point pt;
+ pt.mu_file = "stdin";
+ pt.mu_line = 1;
+ pt.mu_col = 0;
+ rc = mu_sieve_compile_text (mach, script, strlen (script), &pt);
+ }
else
rc = mu_sieve_compile (mach, script);
if (rc)
diff --git a/sieve/tests/i-numeric.at b/sieve/tests/i-numeric.at
index 842661b..a357db4 100644
--- a/sieve/tests/i-numeric.at
+++ b/sieve/tests/i-numeric.at
@@ -38,7 +38,7 @@ if header :comparator "i;ascii-numeric" :contains "X-Number" "15"
discard;
}
],[78],[],
-[sieve: prog:4:1: comparator `i;ascii-numeric' is incompatible with match type `contains' in call to `header'
+[sieve: prog:4.41-49: comparator `i;ascii-numeric' is incompatible with match type `contains' in call to `header'
])
AT_CLEANUP

Return to:

Send suggestions and report system problems to the System administrator.