summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2017-07-01 02:11:16 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2017-07-01 02:18:21 +0300
commitc2e631e78f3259ff189f6cfc9e2c28b371aba361 (patch)
treec90c7ebde0b6a5504efe9380e175f5211f91e876
parent6b16ba1983922772ad47c5feec286e9c940de705 (diff)
downloadmailutils-c2e631e78f3259ff189f6cfc9e2c28b371aba361.tar.gz
mailutils-c2e631e78f3259ff189f6cfc9e2c28b371aba361.tar.bz2
More fixes in MH format parser
* mh/mh_fmtgram.y (codegen_node): Generate mhop_printlit instruction for fmtnode_print node with a literal or number argument. * mh/mh_format.c (mh_fvm_run): Handle mhop_printlit * mh/mh_format.h (mhop_printlit): New opcode. * mh/tests/fmtcomp.at: Update. * mh/tests/fmtfunc.at: Add more tests.
-rw-r--r--mh/mh_fmtgram.y34
-rw-r--r--mh/mh_format.c20
-rw-r--r--mh/mh_format.h4
-rw-r--r--mh/tests/fmtcomp.at51
-rw-r--r--mh/tests/fmtfunc.at70
5 files changed, 135 insertions, 44 deletions
diff --git a/mh/mh_fmtgram.y b/mh/mh_fmtgram.y
index 523bc5c7f..04a890e3d 100644
--- a/mh/mh_fmtgram.y
+++ b/mh/mh_fmtgram.y
@@ -703,13 +703,13 @@ yylex_initial (void)
unput (c);
return token_fmtspec (MH_FMT_DEFAULT);
default:
return bogus ("component or function name expected");
}
}
-
+
c = peek ();
if (c == 0)
return 0;
while ((c = input ()) != 0)
@@ -1389,22 +1389,38 @@ codegen_node (struct mh_format *fmt, struct node *node)
{
if (!node)
return;
switch (node->nodetype)
{
case fmtnode_print:
- codegen_node (fmt, node->v.prt.arg);
- if (node->v.prt.fmtspec)
+ if (node->v.prt.arg->nodetype == fmtnode_literal)
{
- emit_opcode (fmt, mhop_fmtspec);
- emit_instr (fmt, (mh_instr_t) (long) node->v.prt.fmtspec);
+ emit_opcode (fmt, mhop_printlit);
+ emit_string (fmt, node->v.prt.arg->v.str);
+ }
+ else if (node->v.prt.arg->nodetype == fmtnode_number)
+ {
+ char *s;
+ emit_opcode (fmt, mhop_printlit);
+ mu_asprintf (&s, "%ld", node->v.prt.arg->v.num);
+ emit_string (fmt, s);
+ free (s);
+ }
+ else
+ {
+ codegen_node (fmt, node->v.prt.arg);
+ if (node->v.prt.fmtspec)
+ {
+ emit_opcode (fmt, mhop_fmtspec);
+ emit_instr (fmt, (mh_instr_t) (long) node->v.prt.fmtspec);
+ }
+
+ if (node->v.prt.arg->datatype != mhtype_none)
+ emit_opcode_typed (fmt, node->v.prt.arg->datatype,
+ mhop_printn, mhop_prints);
}
-
- if (node->v.prt.arg->datatype != mhtype_none)
- emit_opcode_typed (fmt, node->v.prt.arg->datatype,
- mhop_printn, mhop_prints);
break;
case fmtnode_literal:
emit_opcode (fmt, mhop_sets);
emit_instr (fmt, (mh_instr_t) (long) R_REG);
emit_string (fmt, node->v.str);
diff --git a/mh/mh_format.c b/mh/mh_format.c
index 9b19686e3..914a85b1e 100644
--- a/mh/mh_format.c
+++ b/mh/mh_format.c
@@ -630,12 +630,21 @@ mh_fvm_run (mh_fvm_t mach, mu_message_t msg, size_t msgno)
break;
case mhop_prints:
format_str (mach, mach->str[R_REG].ptr);
break;
+ case mhop_printlit:
+ {
+ size_t skip = MHI_NUM (mach->prog[mach->pc++]);
+ char const *str = MHI_STR (mach->prog[mach->pc]);
+ format_str (mach, str);
+ mach->pc += skip;
+ }
+ break;
+
case mhop_fmtspec:
mach->fmtflags = MHI_NUM (mach->prog[mach->pc++]);
break;
default:
mu_error (_("INTERNAL ERROR: Unknown opcode: %x"), opcode);
@@ -731,13 +740,13 @@ builtin_size (struct mh_fvm *mach)
mach->num[R_REG] = 0;
}
static void
builtin_strlen (struct mh_fvm *mach)
{
- mach->num[R_REG] = mh_string_length (&mach->str[R_ARG]);
+ mach->num[R_REG] = mh_string_length (&mach->str[R_REG]);
}
static void
builtin_width (struct mh_fvm *mach)
{
mach->num[R_REG] = mach->width;
@@ -2049,12 +2058,21 @@ mh_format_dump_disass (mh_format_t fmt)
printf ("printn");
break;
case mhop_prints:
printf ("prints");
break;
+
+ case mhop_printlit:
+ {
+ size_t skip = MHI_NUM (prog[pc++]);
+ char const *str = MHI_STR (prog[pc]);
+ pc += skip;
+ printf ("printlit \"%s\"", str);
+ }
+ break;
case mhop_fmtspec:
{
int fmtspec = MHI_NUM (prog[pc++]);
printf ("fmtspec ");
mh_print_fmtspec (fmtspec);
diff --git a/mh/mh_format.h b/mh/mh_format.h
index afa94a2eb..8e2578683 100644
--- a/mh/mh_format.h
+++ b/mh/mh_format.h
@@ -75,12 +75,16 @@ enum mh_opcode
/* Print num reg */
mhop_printn,
/* Print str reg */
mhop_prints,
+ /* Print literal
+ Format: mhop_printlit length string */
+ mhop_printlit,
+
/* Set format specification.
Format: mhop_fmtspec number */
mhop_fmtspec,
};
enum regid { R_REG, R_ARG };
diff --git a/mh/tests/fmtcomp.at b/mh/tests/fmtcomp.at
index eb21a290c..253ecd9a5 100644
--- a/mh/tests/fmtcomp.at
+++ b/mh/tests/fmtcomp.at
@@ -28,15 +28,14 @@ AT_CHECK([fmtcheck -disass -dump -format '$2'
[$3],[$4])
AT_CLEANUP])
FMTCOMP([literal],
[text],
[PRINT("text")
- 0001: sets reg, "text"
- 0007: prints
- 0008: stop
+ 0001: printlit "text"
+ 0006: stop
])
FMTCOMP([component],
[%{from}],
[PRINT(COMPONENT.from)
0001: ldcomp reg, "from"
@@ -136,36 +135,33 @@ FMTCOMP([nested function calls with typecast],
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
+ 0008: brzs 16
+ 0010: printlit "-"
+ 0014: branch 24
+ 0016: setn reg, 0
+ 0019: sets reg, ""
+ 0024: 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
+ 0008: brzs 16
+ 0010: printlit "-"
+ 0014: branch 20
+ 0016: printlit "+"
+ 0020: stop
])
FMTCOMP([if-elsif-else],
[%<{replied}-%?{encrypted}E%| %>],
[IF (COMPONENT.replied) THEN
PRINT("-")
@@ -174,24 +170,21 @@ ELSE
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
+ 0008: brzs 16
+ 0010: printlit "-"
+ 0014: branch 35
+ 0016: ldcomp reg, "encrypted"
+ 0023: brzs 31
+ 0025: printlit "E"
+ 0029: branch 35
+ 0031: printlit " "
+ 0035: 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.
diff --git a/mh/tests/fmtfunc.at b/mh/tests/fmtfunc.at
index 65107f3ed..a7d72bce5 100644
--- a/mh/tests/fmtfunc.at
+++ b/mh/tests/fmtfunc.at
@@ -81,20 +81,18 @@ FMTFUNC([void],
[
],
[])
FMTFUNC([strlen],
-[%(lit string)
-%(strlen)
+[%(lit string)=%(strlen)
],
[
],
-[string
-6
+[string=6
])
# FIXME: Not quite sure: perhaps it should report 80
FMTFUNC([width],
[%(width)
],
@@ -218,13 +216,13 @@ AT_CHECK([MH_TEST=defined fmtcheck -form input.fmt -width 80 message
[0],
[defined
])
AT_CLEANUP
AT_SETUP([profile])
-AT_KEYWORDS([fmtfunc format])
+AT_KEYWORDS([fmtfunc format])xo
AT_DATA([input.fmt],[%(profile Local-Mailbox)
%(profile undefined)
%(profile moreproc)
])
AT_DATA([message],[
@@ -305,9 +303,71 @@ FMTFUNC([compval],
X-Level: 8
],
[8
])
+# FIXME: This relies on LC_ALL=C
+FMTFUNC([decode],
+[%(decode{Subject})
+],
+[Subject: =?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?= ... =?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=
+
+body
+],
+[If you can read this yo ... u understand the example.
+])
+
+# FIXME: unquote
+
+FMTFUNC([trim],
+[%(void(lit trailing ))%(strlen)
+%(trim)%(strlen)
+],
+[
+
+],
+[12
+8
+])
+
+FMTFUNC([putstr],
+[%(void(lit string))%(putstr)
+%(putstr test)
+%(putstr{from})
+%(putstr(msg))
+],
+[From: foo@example.org
+
+],
+[string
+test
+foo@example.org
+1
+])
+
+# FIXME: putstrf
+
+FMTFUNC([putnum],
+[%(void(num 10))%(putnum)
+%(putnum 15)
+%(putnum{X-Number})
+%(putstr(msg))
+],
+[From: foo@example.org
+X-Number: 8
+
+body
+],
+[10
+15
+8
+1
+])
+
+# FIXME: putnumf
+
+# FIXME: putlit
+
m4_popdef([FMTFUNC]) \ No newline at end of file

Return to:

Send suggestions and report system problems to the System administrator.