summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2017-06-30 19:01:05 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2017-06-30 19:01:05 +0300
commit6b16ba1983922772ad47c5feec286e9c940de705 (patch)
tree146b8faf39047c3c09c6887523dd2b9b3a9d9178
parent5bb282734c5571bba9f3681accabfd6f3b0f4784 (diff)
downloadmailutils-6b16ba1983922772ad47c5feec286e9c940de705.tar.gz
mailutils-6b16ba1983922772ad47c5feec286e9c940de705.tar.bz2
Improve MH format parser.
* mh/fmtcheck.c (main): Assume -dump if no input message and no -disass is given. * mh/mh_fmtgram.y: Enable error-verbose mode (funcall production): Use MHA_OPTARG_NIL flag to provide 0 (or "") default argument. (yyerror): Improve location printer (yylex_initial): Correctly handle %% * mh/mh_format.c (mh_string_move): Rename to mh_string_copy (builtin_msg, builtin_cur): Try to obtain message number only if msgno is 0. (builtin_tab): Fix definitions of comp, lit, and num (mh_format_dump_disass): Print width. * mh/mh_format.h (MHA_OPTARG_NIL): New flag. * mh/tests/fmtcomp.at: New file. * mh/tests/fmtfunc.at: New file. * mh/tests/Makefile.am: Add new files. * mh/tests/testsuite.at: Likewise. * mh/tests/atlocal.in (MHETCDIR): New variable. * mh/tests/scan.at: Test external formats.
-rw-r--r--mh/fmtcheck.c3
-rw-r--r--mh/mh_fmtgram.y59
-rw-r--r--mh/mh_format.c26
-rw-r--r--mh/mh_format.h1
-rw-r--r--mh/tests/Makefile.am2
-rw-r--r--mh/tests/atlocal.in1
-rw-r--r--mh/tests/fmtcomp.at318
-rw-r--r--mh/tests/fmtfunc.at313
-rw-r--r--mh/tests/scan.at60
-rw-r--r--mh/tests/testsuite.at2
10 files changed, 755 insertions, 30 deletions
diff --git a/mh/fmtcheck.c b/mh/fmtcheck.c
index b7ab6a1d8..8c8509744 100644
--- a/mh/fmtcheck.c
+++ b/mh/fmtcheck.c
@@ -97,7 +97,8 @@ main (int argc, char **argv)
switch (argc)
{
case 0:
- dump_option = 1;
+ if (!disass_option)
+ dump_option = 1;
break;
case 1:
diff --git a/mh/mh_fmtgram.y b/mh/mh_fmtgram.y
index 084445d3f..523bc5c7f 100644
--- a/mh/mh_fmtgram.y
+++ b/mh/mh_fmtgram.y
@@ -137,14 +137,14 @@ static struct node *typecast (struct node *node, enum mh_type type);
} arg;
};
-%token <num> NUMBER
-%token <str> STRING COMPONENT
-%token <arg> ARGUMENT
-%token <builtin> FUNCTION
-%token IF ELIF ELSE FI
-%token <fmtspec> FMTSPEC
+%token <num> NUMBER "number"
+%token <str> STRING "string" COMPONENT "component"
+%token <arg> ARGUMENT "argument"
+%token <builtin> FUNCTION "function name"
+%token IF "%<" ELIF "%?" ELSE "%|" FI "%>"
+%token <fmtspec> FMTSPEC "format specifier"
%token BOGUS
-%token EOFN
+%token EOFN ")"
%type <nodelist> list zlist elif_list
%type <nodeptr> item escape component funcall cntl argument
@@ -152,6 +152,8 @@ static struct node *typecast (struct node *node, enum mh_type type);
%type <builtin> function
%type <fmtspec> fmtspec
+%error-verbose
+
%%
input : list
@@ -234,14 +236,28 @@ funcall : function argument EOFN
}
else if (arg == NULL)
{
- if (($1->optarg & MHA_LITERAL)
- && $1->argtype == mhtype_str)
+ if ($1->optarg & MHA_OPTARG_NIL)
{
- arg = new_node (fmtnode_literal, mhtype_str);
- arg->v.str = "";
+ switch ($1->argtype)
+ {
+ case mhtype_str:
+ arg = new_node (fmtnode_literal, mhtype_str);
+ arg->v.str = "";
+ break;
+
+ case mhtype_num:
+ arg = new_node (fmtnode_number, mhtype_num);
+ arg->v.num = 0;
+ break;
+
+ default:
+ abort ();
+ }
}
else if ($1->optarg & MHA_OPTARG)
- /* ok - ignore */;
+ {
+ /* ok - ignore */;
+ }
else
{
yyerror ("required argument missing");
@@ -535,11 +551,16 @@ yyerror (const char *s)
mu_stream_write (mu_strerr, bol + i, 1, NULL);
}
mu_stream_write (mu_strerr, "\n", 1, NULL);
- mu_error ("%*.*s^%*.*s^",
- b + yylloc.beg.mu_col - 1,
- b + yylloc.beg.mu_col - 1, "",
- e + yylloc.end.mu_col - yylloc.beg.mu_col - b - 1,
- e + yylloc.end.mu_col - yylloc.beg.mu_col - b - 1, "");
+ if (mu_locus_point_eq (&yylloc.beg, &yylloc.end))
+ mu_error ("%*.*s^",
+ b + yylloc.beg.mu_col - 1,
+ b + yylloc.beg.mu_col - 1, "");
+ else
+ mu_error ("%*.*s^%*.*s^",
+ b + yylloc.beg.mu_col - 1,
+ b + yylloc.beg.mu_col - 1, "",
+ e + yylloc.end.mu_col - yylloc.beg.mu_col - b - 1,
+ e + yylloc.end.mu_col - yylloc.beg.mu_col - b - 1, "");
}
return 0;
}
@@ -666,7 +687,9 @@ yylex_initial (void)
case '<':
return IF;
case '%':
- return '%';
+ unput (c);
+ unput (c);
+ break;
case '(':
unput (c);
return token_function ();
diff --git a/mh/mh_format.c b/mh/mh_format.c
index 50f84f239..9b19686e3 100644
--- a/mh/mh_format.c
+++ b/mh/mh_format.c
@@ -97,7 +97,7 @@ mh_string_load (struct mh_string *s, char const *str)
}
static void
-mh_string_move (struct mh_fvm *mach, enum regid dst, enum regid src)
+mh_string_copy (struct mh_fvm *mach, enum regid dst, enum regid src)
{
mh_string_load (&mach->str[dst], mach->str[src].ptr);
}
@@ -546,7 +546,7 @@ mh_fvm_run (mh_fvm_t mach, mu_message_t msg, size_t msgno)
{
long dst = MHI_NUM (mach->prog[mach->pc++]);
long src = MHI_NUM (mach->prog[mach->pc++]);
- mh_string_move (mach, dst, src);
+ mh_string_copy (mach, dst, src);
/* FIXME: perhaps copy, not move? */
}
break;
@@ -696,7 +696,8 @@ static void
builtin_msg (struct mh_fvm *mach)
{
size_t msgno = mach->msgno;
- mh_message_number (mach->message, &msgno);
+ if (msgno == 0)
+ mh_message_number (mach->message, &msgno);
mach->num[R_REG] = msgno;
}
@@ -714,7 +715,8 @@ builtin_cur (struct mh_fvm *mach)
mu_diag_funcall (MU_DIAG_ERROR, "mu_message_get_mailbox", NULL, rc);
exit (1);
}
- mh_message_number (mach->message, &msgno);
+ if (msgno == 0)
+ mh_message_number (mach->message, &msgno);
mh_mailbox_get_cur (mbox, &cur); /* FIXME: Cache this */
mach->num[R_REG] = msgno == cur;
}
@@ -795,7 +797,8 @@ builtin_amatch (struct mh_fvm *mach)
{
char const *arg = mh_string_value (&mach->str[R_ARG]);
size_t len = strlen (arg);
- mach->num[R_REG] = strncmp (mh_string_value (&mach->str[R_REG]), arg, len);
+ mach->num[R_REG] =
+ strncmp (mh_string_value (&mach->str[R_REG]), arg, len) == 0;
}
static void
@@ -844,7 +847,7 @@ builtin_num (struct mh_fvm *mach)
static void
builtin_lit (struct mh_fvm *mach)
{
- mh_string_move (mach, R_REG, R_ARG);
+ mh_string_copy (mach, R_REG, R_ARG);
}
static void
@@ -891,7 +894,7 @@ static void
builtin_comp (struct mh_fvm *mach)
{
/* FIXME: Check this */
- mh_string_move (mach, R_REG, R_ARG);
+ mh_string_copy (mach, R_REG, R_ARG);
}
/* compval comp integer num set to "atoi(comp)"*/
@@ -1198,7 +1201,7 @@ builtin_szone (struct mh_fvm *mach)
static void
builtin_str_noop (struct mh_fvm *mach)
{
- mh_string_move (mach, R_REG, R_ARG);
+ mh_string_copy (mach, R_REG, R_ARG);
}
/* date2local date coerce date to local timezone*/
@@ -1830,15 +1833,15 @@ mh_builtin_t builtin_tab[] = {
{ "minus", builtin_minus, mhtype_num, mhtype_num, MHA_LITERAL },
{ "divide", builtin_divide, mhtype_num, mhtype_num, MHA_LITERAL },
{ "modulo", builtin_modulo, mhtype_num, mhtype_num, MHA_LITERAL },
- { "num", builtin_num, mhtype_num, mhtype_num, MHA_LITERAL },
- { "lit", builtin_lit, mhtype_str, mhtype_str, MHA_LITERAL },
+ { "num", builtin_num, mhtype_num, mhtype_num, MHA_LITERAL|MHA_OPTARG|MHA_OPTARG_NIL },
+ { "lit", builtin_lit, mhtype_str, mhtype_str, MHA_LITERAL|MHA_OPTARG|MHA_OPTARG_NIL },
{ "getenv", builtin_getenv, mhtype_str, mhtype_str, MHA_LITERAL },
{ "profile", builtin_profile, mhtype_str, mhtype_str, MHA_LITERAL },
{ "nonzero", builtin_nonzero, mhtype_num, mhtype_num, MHA_OPTARG },
{ "zero", builtin_zero, mhtype_num, mhtype_num, MHA_OPTARG },
{ "null", builtin_null, mhtype_num, mhtype_str, MHA_OPTARG },
{ "nonnull", builtin_nonnull, mhtype_num, mhtype_str, MHA_OPTARG },
- { "comp", builtin_comp, mhtype_num, mhtype_str, MHA_OPTARG },
+ { "comp", builtin_comp, mhtype_str, mhtype_str },
{ "compval", builtin_compval, mhtype_num, mhtype_str },
{ "trim", builtin_trim, mhtype_none, mhtype_str, MHA_OPTARG },
{ "putstr", builtin_putstr, mhtype_none, mhtype_str, MHA_OPTARG },
@@ -2055,6 +2058,7 @@ mh_format_dump_disass (mh_format_t fmt)
int fmtspec = MHI_NUM (prog[pc++]);
printf ("fmtspec ");
mh_print_fmtspec (fmtspec);
+ printf(", %d", fmtspec & MH_WIDTH_MASK);
}
break;
diff --git a/mh/mh_format.h b/mh/mh_format.h
index d0de79f8d..afa94a2eb 100644
--- a/mh/mh_format.h
+++ b/mh/mh_format.h
@@ -126,6 +126,7 @@ struct mh_format
#define MHA_OPTARG 0x1
#define MHA_LITERAL 0x2
#define MHA_VOID 0x4
+#define MHA_OPTARG_NIL 0x8
typedef struct mh_builtin mh_builtin_t;
diff --git a/mh/tests/Makefile.am b/mh/tests/Makefile.am
index 27e5dfa9c..df74d2089 100644
--- a/mh/tests/Makefile.am
+++ b/mh/tests/Makefile.am
@@ -50,6 +50,8 @@ TESTSUITE_AT = \
anno.at\
burst.at\
comp.at\
+ fmtcomp.at\
+ fmtfunc.at\
folder.at\
forw.at\
inc.at\
diff --git a/mh/tests/atlocal.in b/mh/tests/atlocal.in
index 6a7f40528..086ed8939 100644
--- a/mh/tests/atlocal.in
+++ b/mh/tests/atlocal.in
@@ -4,6 +4,7 @@
# Inc.
PATH=@abs_builddir@:@abs_top_builddir@/testsuite:@abs_top_builddir@/mh:$top_srcdir:$srcdir:$PATH
+MHETCDIR=@abs_top_srcdir@/mh/etc
# mimeflt [FILE]
# Filter out all variable information from a MIME message in FILE.
diff --git a/mh/tests/fmtcomp.at b/mh/tests/fmtcomp.at
new file mode 100644
index 000000000..eb21a290c
--- /dev/null
+++ b/mh/tests/fmtcomp.at
@@ -0,0 +1,318 @@
+# This file is part of GNU Mailutils. -*- Autotest -*-
+# Copyright (C) 2010-2012, 2014-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(Format compilation)
+
+dnl ------------------------------------------------------------
+dnl fmtcheck([NAME], [INPUT], [STDOUT = `'], [STDERR = `'])
+dnl
+m4_pushdef([FMTCOMP],[
+AT_SETUP([$1])
+AT_KEYWORDS([format fmtcomp])
+AT_CHECK([fmtcheck -disass -dump -format '$2'
+],
+[m4_if([$4],[],[0],[1])],
+[$3],[$4])
+AT_CLEANUP])
+
+FMTCOMP([literal],
+[text],
+[PRINT("text")
+ 0001: sets reg, "text"
+ 0007: prints
+ 0008: stop
+])
+
+FMTCOMP([component],
+[%{from}],
+[PRINT(COMPONENT.from)
+ 0001: ldcomp reg, "from"
+ 0007: prints
+ 0008: stop
+])
+
+FMTCOMP([component formatted],
+[%-40{from}],
+[FORMAT(RALIGN|NOZEROPAD|NOCOMPWS, 40, COMPONENT.from)
+ 0001: ldcomp reg, "from"
+ 0007: fmtspec RALIGN|NOZEROPAD|NOCOMPWS, 40
+ 0009: prints
+ 0010: stop
+])
+
+FMTCOMP([function call],
+[%(msg)],
+[PRINT(msg())
+ 0001: call msg
+ 0003: printn
+ 0004: stop
+])
+
+FMTCOMP([function call formatted],
+[%08(msg)],
+[FORMAT(NORALIGN|ZEROPAD|NOCOMPWS, 8, msg())
+ 0001: call msg
+ 0003: fmtspec NORALIGN|ZEROPAD|NOCOMPWS, 8
+ 0005: printn
+ 0006: stop
+])
+
+FMTCOMP([function call with argument],
+[%(lit text: )],
+[PRINT(lit("text: "))
+ 0001: sets arg, "text: "
+ 0007: call lit
+ 0009: prints
+ 0010: stop
+])
+
+FMTCOMP([function call with numeric argument],
+[%(num 10)],
+[PRINT(num(10))
+ 0001: setn arg, 10
+ 0004: call num
+ 0006: printn
+ 0007: stop
+])
+
+FMTCOMP([function call with numeric argument and format spec],
+[%08(num 10)],
+[FORMAT(NORALIGN|ZEROPAD|NOCOMPWS, 8, num(10))
+ 0001: setn arg, 10
+ 0004: call num
+ 0006: fmtspec NORALIGN|ZEROPAD|NOCOMPWS, 8
+ 0008: printn
+ 0009: stop
+])
+
+FMTCOMP([function call with component argument],
+[%(decode{subject})],
+[PRINT(decode(COMPONENT.subject))
+ 0001: ldcomp reg, "subject"
+ 0008: movs arg, reg
+ 0011: call decode
+ 0013: prints
+ 0014: stop
+])
+
+FMTCOMP([nested function calls],
+[%(null(decode{subject}))],
+[PRINT(null(decode(COMPONENT.subject)))
+ 0001: ldcomp reg, "subject"
+ 0008: movs arg, reg
+ 0011: call decode
+ 0013: movs arg, reg
+ 0016: call null
+ 0018: printn
+ 0019: stop
+])
+
+FMTCOMP([nested function calls with typecast],
+[%(zero(decode{subject}))],
+[PRINT(zero(NUM(decode(COMPONENT.subject))))
+ 0001: ldcomp reg, "subject"
+ 0008: movs arg, reg
+ 0011: call decode
+ 0013: atoi
+ 0014: movn arg, reg
+ 0017: call zero
+ 0019: printn
+ 0020: stop
+])
+
+FMTCOMP([simple conditional],
+[%<{replied}-%>],
+[IF (COMPONENT.replied) THEN
+ PRINT("-")
+FI
+ 0001: ldcomp reg, "replied"
+ 0008: brzs 18
+ 0010: sets reg, "-"
+ 0015: prints
+ 0016: branch 26
+ 0018: setn reg, 0
+ 0021: sets reg, ""
+ 0026: stop
+],[],[-format])
+
+FMTCOMP([if-else],
+[%<{replied}-%|+%>],
+[IF (COMPONENT.replied) THEN
+ PRINT("-")
+ELSE
+ PRINT("+")
+FI
+ 0001: ldcomp reg, "replied"
+ 0008: brzs 18
+ 0010: sets reg, "-"
+ 0015: prints
+ 0016: branch 24
+ 0018: sets reg, "+"
+ 0023: prints
+ 0024: stop
+])
+
+FMTCOMP([if-elsif-else],
+[%<{replied}-%?{encrypted}E%| %>],
+[IF (COMPONENT.replied) THEN
+ PRINT("-")
+ELSE
+ IF (COMPONENT.encrypted) THEN
+ PRINT("E")
+ ELSE
+ PRINT(" ")
+ FI
+FI
+ 0001: ldcomp reg, "replied"
+ 0008: brzs 18
+ 0010: sets reg, "-"
+ 0015: prints
+ 0016: branch 41
+ 0018: ldcomp reg, "encrypted"
+ 0025: brzs 35
+ 0027: sets reg, "E"
+ 0032: prints
+ 0033: branch 41
+ 0035: sets reg, " "
+ 0040: prints
+ 0041: stop
+])
+
+# The example below is taken from mh-format(1), subsection
+# "Other Hints and Tips".
+# It issues a spurious PRINT instruction, which is intended. The following
+# testcase uses a fixed version.
+FMTCOMP([inline conditional],
+[%(formataddr %<{reply-to}%|%{from}%>)],
+[formataddr(IF (COMPONENT.reply-to) THEN; ; ELSE PRINT(COMPONENT.from); FI)
+ 0001: ldcomp reg, "reply-to"
+ 0008: brzs 12
+ 0010: branch 19
+ 0012: ldcomp reg, "from"
+ 0018: prints
+ 0019: movs arg, reg
+ 0022: call formataddr
+ 0024: stop
+])
+
+FMTCOMP([inline conditional (2)],
+[%(formataddr %<{reply-to}%|%(void{from})%>)],
+[formataddr(IF (COMPONENT.reply-to) THEN; ; ELSE COMPONENT.from; FI)
+ 0001: ldcomp reg, "reply-to"
+ 0008: brzs 12
+ 0010: branch 18
+ 0012: ldcomp reg, "from"
+ 0018: movs arg, reg
+ 0021: call formataddr
+ 0023: stop
+])
+
+FMTCOMP([statement list],
+[%(formataddr %<{reply-to}%|%(void{from})%>)%(void(width))%(putaddr To: )],
+[formataddr(IF (COMPONENT.reply-to) THEN; ; ELSE COMPONENT.from; FI)
+width()
+putaddr("To: ")
+ 0001: ldcomp reg, "reply-to"
+ 0008: brzs 12
+ 0010: branch 18
+ 0012: ldcomp reg, "from"
+ 0018: movs arg, reg
+ 0021: call formataddr
+ 0023: call width
+ 0025: sets arg, "To: "
+ 0031: call putaddr
+ 0033: stop
+])
+
+m4_popdef[FMTCOMP])
+
+# FMTCOMP(NAME,INPUT,ERR)
+m4_pushdef([FMTCOMP],[
+AT_SETUP([$1])
+AT_KEYWORDS([format fmtdiag])
+AT_DATA([input.fmt],[$2])
+AT_CHECK([fmtcheck -form input.fmt
+],
+[1],
+[],
+[$3])
+AT_CLEANUP])
+
+AT_BANNER(Format error diagnostics)
+
+FMTCOMP([unknown function],
+[%; comment
+test %(function)
+],
+[fmtcheck: input.fmt:2.8-15: unknown function
+fmtcheck: test %(function)
+fmtcheck: ^ ^
+])
+
+FMTCOMP([condition syntax],
+[%<%{reply-to}%|%{from}%>
+],
+[[fmtcheck: input.fmt:1.1-2: '(' or '{' expected]
+fmtcheck: %<%{reply-to}%|%{from}%>
+fmtcheck: ^^
+])
+
+FMTCOMP([unclosed control],
+[%<{reply-to}%|%{from}>
+],
+[fmtcheck: input.fmt:1.22: syntax error, unexpected $end, expecting %>
+fmtcheck: %<{reply-to}%|%{from}
+fmtcheck: ^
+])
+
+FMTCOMP([extra ELSE],
+[%<{reply-to}%|test%|test%>
+],
+[fmtcheck: input.fmt:1.19-20: syntax error, unexpected %|, expecting %>
+fmtcheck: %<{reply-to}%|test%|test%>
+fmtcheck: ^^
+])
+
+# FIXME: Error locations in the following tests could be improved, if
+# %locations were enabled.
+
+FMTCOMP([unwanted argument],
+[%(msg 10)
+],
+[fmtcheck: input.fmt:1.9: function doesn't take arguments
+fmtcheck: %(msg 10)
+fmtcheck: ^
+])
+
+FMTCOMP([missing argument],
+[%(decode)
+],
+[fmtcheck: input.fmt:1.9: required argument missing
+fmtcheck: %(decode)
+fmtcheck: ^
+])
+
+FMTCOMP([argument type mismatch],
+[%(lit{comp})
+],
+[fmtcheck: input.fmt:1.12: argument must be literal
+fmtcheck: %(lit{comp})
+fmtcheck: ^
+])
+
+m4_popdef[FMTCOMP])
+
+# End of fmtcomp.at
diff --git a/mh/tests/fmtfunc.at b/mh/tests/fmtfunc.at
new file mode 100644
index 000000000..65107f3ed
--- /dev/null
+++ b/mh/tests/fmtfunc.at
@@ -0,0 +1,313 @@
+# This file is part of GNU Mailutils. -*- Autotest -*-
+# Copyright (C) 2010-2012, 2014-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(Format functions)
+
+dnl ------------------------------------------------------------
+dnl fmtrun([NAME], [FORMAT], [MSG], [STDOUT = `'], [STDERR = `'])
+dnl
+m4_pushdef([FMTFUNC],[
+AT_SETUP([$1])
+AT_KEYWORDS([fmtfunc format])
+AT_DATA([input.fmt],[$2])
+AT_DATA([message],[$3])
+AT_CHECK([fmtcheck -form input.fmt -msgno 1 -width 80 message
+],
+[m4_if([$5],[],[0],[1])],
+[$4],[$5])
+AT_CLEANUP])
+
+FMTFUNC([msg],
+[%(msg)
+],
+[
+
+],
+[1
+])
+
+# FIXME: cur
+# FIXME: unseen
+
+FMTFUNC([size],
+[%(size)
+],
+[From: gray@example.net
+To: root@example.com
+Subject: Test
+
+test message
+],
+[72
+])
+
+FMTFUNC([num],
+[%(num 10)
+%(num)
+],
+[
+
+],
+[10
+0
+])
+
+FMTFUNC([lit],
+[%(lit string)
+%(lit)
+],
+[
+
+],
+[string
+])
+
+FMTFUNC([void],
+[%(void(num 10))
+],
+[
+
+],
+[])
+
+FMTFUNC([strlen],
+[%(lit string)
+%(strlen)
+],
+[
+
+],
+[string
+6
+])
+
+# FIXME: Not quite sure: perhaps it should report 80
+FMTFUNC([width],
+[%(width)
+],
+[
+
+],
+[79
+])
+
+FMTFUNC([charleft],
+[input %(charleft)
+],
+[
+
+],
+[input 73
+])
+
+# FIXME: timenow
+# FIXME: ne
+# FIXME: myhost
+# FIXME: myname
+# FIXME: localmbox
+
+FMTFUNC([eq],
+[%(void(num 10))%(eq 5):%(void(num 5))%(eq 5)
+],
+[
+
+],
+[0:1
+])
+
+FMTFUNC([ne],
+[%(void(num 10))%(ne 5):%(void(num 5))%(ne 5)
+],
+[
+
+],
+[1:0
+])
+
+FMTFUNC([gt],
+[%(void(num 10))%(gt 5):%(void(num 3))%(gt 5)
+],
+[
+
+],
+[1:0
+])
+
+FMTFUNC([match],
+[%(void(lit a stringent test))%(match string)
+%(void(lit one more test))%(match string)
+],
+[
+
+],
+[1
+0
+])
+
+FMTFUNC([amatch],
+[%(void(lit stringent test))%(amatch string)
+%(void(lit a stringent test))%(amatch string)
+],
+[
+
+],
+[1
+0
+])
+
+FMTFUNC([plus],
+[%(void(num 10))%(plus 15)
+],
+[
+
+],
+[25
+])
+
+FMTFUNC([minus],
+[%(void(num 10))%(minus 15)
+],
+[
+
+],
+[-5
+])
+
+FMTFUNC([divide],
+[%(void(num 10))%(divide 2)
+],
+[
+
+],
+[5
+])
+
+FMTFUNC([modulo],
+[%(void(num 10))%(modulo 2)
+%(void(num 5))%(modulo 2)
+],
+[
+
+],
+[0
+1
+])
+
+AT_SETUP([getenv])
+AT_KEYWORDS([fmtfunc format])
+AT_DATA([input.fmt],[%(getenv MH_TEST)
+])
+AT_DATA([message],[
+
+])
+AT_CHECK([MH_TEST=defined fmtcheck -form input.fmt -width 80 message
+],
+[0],
+[defined
+])
+AT_CLEANUP
+
+AT_SETUP([profile])
+AT_KEYWORDS([fmtfunc format])
+AT_DATA([input.fmt],[%(profile Local-Mailbox)
+%(profile undefined)
+%(profile moreproc)
+])
+AT_DATA([message],[
+
+])
+AT_DATA([mh_profile],[Local-Mailbox: foo@example.org
+moreproc: simple-more
+])
+AT_CHECK([MH=`pwd`/mh_profile fmtcheck -form input.fmt -width 80 message
+],
+[0],
+[foo@example.org
+
+simple-more
+])
+AT_CLEANUP
+
+FMTFUNC([nonzero],
+[%(nonzero(num 10))
+%(nonzero(num))
+%(void(width))%(nonzero)
+],
+[
+
+],
+[1
+0
+1
+])
+
+FMTFUNC([zero],
+[%(zero(num 10))
+%(zero(num))
+%(void(width))%(zero)
+],
+[
+
+],
+[0
+1
+0
+])
+
+FMTFUNC([null],
+[%(lit input)%(null)
+%(lit)%(null)
+],
+[
+
+],
+[input0
+1
+])
+
+FMTFUNC([nonnull],
+[%(lit input)%(nonnull)
+%(lit)%(nonnull)
+],
+[
+
+],
+[input1
+0
+])
+
+FMTFUNC([comp],
+[%(comp{From})
+],
+[From: foo@example.com
+
+],
+[foo@example.com
+])
+
+FMTFUNC([compval],
+[%(comp{X-Level})
+],
+[From: foo@example.com
+X-Level: 8
+
+],
+[8
+])
+
+
+
+m4_popdef([FMTFUNC]) \ No newline at end of file
diff --git a/mh/tests/scan.at b/mh/tests/scan.at
index 118a51b8b..062356be6 100644
--- a/mh/tests/scan.at
+++ b/mh/tests/scan.at
@@ -93,5 +93,65 @@ scan | sed 's/ *$//'
5 07/13 To:Foo Bar Empty MIME Parts<<------- =_aaaaaaaaaa0 Content-
])
+MH_CHECK([default format],[scan06 scan.default],[
+MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox],[700])
+scan -form $MHETCDIR/scan.default| sed 's/ *$//'
+],
+[0],
+[ 1 12/28 Foo Bar Jabberwocky<<`Twas brillig, and the slithy toves
+ 2 12/28 Bar Re: Jabberwocky<<It seems very pretty, but it's
+ 3 07/13 Sergey Poznyakoff Simple MIME<<------- =_aaaaaaaaaa0 Content-Type:
+ 4 07/13 Sergey Poznyakoff Nested MIME<<------- =_aaaaaaaaaa0 Content-Type:
+ 5 07/13 Sergey Poznyakoff Empty MIME Parts<<------- =_aaaaaaaaaa0 Content-
+])
+
+MH_CHECK([mailx format],[scan07 scan.mailx],[
+MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox],[700])
+scan -form $MHETCDIR/scan.mailx| sed 's/ *$//'
+],
+[0],
+[ N 1 Foo Bar Fri Dec 28 22:18 Jabberwocky
+ N 2 Bar Fri Dec 28 23:28 Re: Jabberwocky
+ N 3 Sergey Poznyakoff Sat Jul 13 00:43 Simple MIME
+ N 4 Sergey Poznyakoff Sat Jul 13 00:50 Nested MIME
+ N 5 Sergey Poznyakoff Sat Jul 13 00:43 Empty MIME Parts
+])
+
+MH_CHECK([size format],[scan08 scan.size],[
+MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox],[700])
+scan -form $MHETCDIR/scan.size| sed 's/ *$//'
+],
+[0],
+[ 1 12/28 1354 Foo Bar Jabberwocky<<`Twas brillig, and the slithy
+ 2 12/28 614 Bar Re: Jabberwocky<<It seems very pretty, but
+ 3 07/13 1647 Sergey Poznyakoff Simple MIME<<------- =_aaaaaaaaaa0 Content
+ 4 07/13 3477 Sergey Poznyakoff Nested MIME<<------- =_aaaaaaaaaa0 Content
+ 5 07/13 935 Sergey Poznyakoff Empty MIME Parts<<------- =_aaaaaaaaaa0 Co
+])
+
+MH_CHECK([time format],[scan08 scan.time],[
+MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox],[700])
+scan -form $MHETCDIR/scan.time| sed 's/ *$//'
+],
+[0],
+[ 1 12/28 22:18+02 Foo Bar Jabberwocky<<`Twas brillig, and the sli
+ 2 12/28 23:28+02 Bar Re: Jabberwocky<<It seems very pretty,
+ 3 07/13 00:43+03 Sergey Poznyakoff Simple MIME<<------- =_aaaaaaaaaa0 Cont
+ 4 07/13 00:50+03 Sergey Poznyakoff Nested MIME<<------- =_aaaaaaaaaa0 Cont
+ 5 07/13 00:43+03 Sergey Poznyakoff Empty MIME Parts<<------- =_aaaaaaaaaa0
+])
+
+MH_CHECK([timely format],[scan09 scan.timely],[
+MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox],[700])
+scan -form $MHETCDIR/scan.timely| sed 's/ *$//'
+],
+[0],
+[ 1 Dec01 Foo Bar Jabberwocky<<`Twas brillig, and the slithy toves
+ 2 Dec01 Bar Re: Jabberwocky<<It seems very pretty, but it's
+ 3 Jul02 Sergey Poznyakoff Simple MIME<<------- =_aaaaaaaaaa0 Content-Type:
+ 4 Jul02 Sergey Poznyakoff Nested MIME<<------- =_aaaaaaaaaa0 Content-Type:
+ 5 Jul02 Sergey Poznyakoff Empty MIME Parts<<------- =_aaaaaaaaaa0 Content-
+])
+
m4_popdef[MH_KEYWORDS])
# End of scan.at
diff --git a/mh/tests/testsuite.at b/mh/tests/testsuite.at
index b1d7a7338..c6820843c 100644
--- a/mh/tests/testsuite.at
+++ b/mh/tests/testsuite.at
@@ -63,6 +63,8 @@ AT_CLEANUP
AT_INIT
m4_include([install-mh.at])
+m4_include([fmtcomp.at])
+m4_include([fmtfunc.at])
m4_include([mhseq.at])
m4_include([ali.at])
m4_include([folder.at])

Return to:

Send suggestions and report system problems to the System administrator.