summaryrefslogtreecommitdiff
path: root/mh
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2017-07-03 12:41:42 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2017-07-03 12:41:42 +0300
commit7790c66bf2e26a4f34f2b42766d92e6c61f3930d (patch)
treeabb337e47be4fbaac5a533dc936019223c9f01a3 /mh
parentace54abd2ddae8facfce059d9442866517fc4b58 (diff)
downloadmailutils-7790c66bf2e26a4f34f2b42766d92e6c61f3930d.tar.gz
mailutils-7790c66bf2e26a4f34f2b42766d92e6c61f3930d.tar.bz2
fmtcheck: use symbolic label names by default
Actual program counters may differ between different architecture, so avoid using them in the testsuite. * mh/fmtcheck.c: New option -pc requires printing program counters. Unless this option is used, -disass prints only labels where needed. * mh/mh.h (mh_format_dump_disass): Change signature. * mh/mh_format.c (mh_format_dump_disass): Take additional flag indicating whether to print program counters. Compute and print program labels, unless this flag is non-zero. * mh/tests/fmtcomp.at: Don't expect program counters in disassembled code.
Diffstat (limited to 'mh')
-rw-r--r--mh/fmtcheck.c12
-rw-r--r--mh/mh.h2
-rw-r--r--mh/mh_format.c167
-rw-r--r--mh/tests/fmtcomp.at228
4 files changed, 286 insertions, 123 deletions
diff --git a/mh/fmtcheck.c b/mh/fmtcheck.c
index 8c8509744..b0d7d37e2 100644
--- a/mh/fmtcheck.c
+++ b/mh/fmtcheck.c
@@ -31,6 +31,7 @@ static int debug_option;
static char *input_file;
static size_t width;
static size_t msgno;
+static int pc_option;
void
opt_formfile (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
@@ -58,12 +59,15 @@ static struct mu_option options[] = {
{ "format", 0, N_("FORMAT"), MU_OPTION_DEFAULT,
N_("use this format string"),
mu_c_string, NULL, opt_format },
- { "dump", 0, NULL, MU_OPTION_HIDDEN,
+ { "dump", 0, NULL, MU_OPTION_DEFAULT,
N_("dump the listing of compiled format code"),
mu_c_bool, &dump_option },
- { "disassemble", 0, NULL, MU_OPTION_HIDDEN,
+ { "disassemble", 0, NULL, MU_OPTION_DEFAULT,
N_("dump disassembled format code"),
mu_c_bool, &disass_option },
+ { "pc", 0, NULL, MU_OPTION_DEFAULT,
+ N_("print program counter along with disassembled code (implies --disassemble)"),
+ mu_c_bool, &pc_option },
{ "debug", 0, NULL, MU_OPTION_DEFAULT,
N_("enable parser debugging output"),
mu_c_bool, &debug_option },
@@ -94,6 +98,8 @@ int
main (int argc, char **argv)
{
mh_getopt (&argc, &argv, options, 0, args_doc, prog_doc, NULL);
+ if (pc_option)
+ disass_option = 1;
switch (argc)
{
case 0:
@@ -123,7 +129,7 @@ main (int argc, char **argv)
if (dump_option)
mh_format_dump_code (format);
if (disass_option)
- mh_format_dump_disass (format);
+ mh_format_dump_disass (format, pc_option);
if (input_file)
run ();
diff --git a/mh/mh.h b/mh/mh.h
index 312f9b0bc..c1d8ee85a 100644
--- a/mh/mh.h
+++ b/mh/mh.h
@@ -182,7 +182,7 @@ void mh_fvm_run (mh_fvm_t fvm, mu_message_t msg, size_t msgno);
int mh_format_str (mh_format_t fmt, char *str, size_t width, char **pret);
void mh_format_dump_code (mh_format_t fmt);
-void mh_format_dump_disass (mh_format_t fmt);
+void mh_format_dump_disass (mh_format_t fmt, int addr);
#define MH_FMT_PARSE_DEFAULT 0
#define MH_FMT_PARSE_TREE 0x01
diff --git a/mh/mh_format.c b/mh/mh_format.c
index 86eeb4ff3..0f1d4b728 100644
--- a/mh/mh_format.c
+++ b/mh/mh_format.c
@@ -1896,8 +1896,128 @@ _get_builtin_name (mh_builtin_fp ptr)
return NULL;
}
+/* Label array is used when disassembling the code, in order to create.
+ meaningful label names. The array elements starting from index 1 keep
+ the code addesses to which branch instructions point, in ascending order.
+ Element 0 keeps the number of addresses stored. Thus, the label
+ array LAB with contents { 3, 2, 5, 7 } declares three labels: "L1" on
+ address 2, "L2", on address 5, and "L3" on address 7.
+*/
+
+/* Find in LAB the index of the label corresponding to the given PC. Return
+ 0 if no label found. */
+size_t
+find_label (size_t *lab, size_t pc)
+{
+ if (lab)
+ {
+ size_t i;
+ for (i = 1; i <= lab[0]; i++)
+ {
+ if (lab[i] == pc)
+ return i;
+ }
+ }
+ return 0;
+}
+
+static int
+comp_pc (const void *a, const void *b)
+{
+ size_t pca = *(size_t*)a;
+ size_t pcb = *(size_t*)b;
+ if (pca < pcb)
+ return -1;
+ else if (pca > pcb)
+ return 1;
+ return 0;
+}
+
+/* Extract a label array from a compiled format FMT. */
+static size_t *
+extract_labels (mh_format_t fmt)
+{
+ size_t *lab;
+ size_t pc;
+ long n;
+
+ lab = mu_calloc (fmt->progcnt, sizeof (lab[0]));
+ lab[0] = 0;
+ for (pc = 1; pc < fmt->progcnt; )
+ {
+ mh_opcode_t opcode = MHI_OPCODE (fmt->prog[pc++]);
+ if (opcode == mhop_stop)
+ break;
+ switch (opcode)
+ {
+ case mhop_branch:
+ case mhop_brzn:
+ case mhop_brzs:
+ n = MHI_NUM (fmt->prog[pc++]);
+ if (!find_label (lab, pc + n - 1))
+ lab[++lab[0]] = pc + n - 1;
+ break;
+
+ case mhop_setn:
+ pc += 2;
+ break;
+
+ case mhop_sets:
+ case mhop_ldcomp:
+ pc += 2 + MHI_NUM (fmt->prog[pc + 1]);
+ break;
+
+ case mhop_movn:
+ case mhop_movs:
+ pc += 2;
+ break;
+
+ case mhop_ldbody:
+ case mhop_call:
+ case mhop_fmtspec:
+ pc++;
+ break;
+
+ case mhop_printlit:
+ pc += 1 + MHI_NUM (fmt->prog[pc]);
+ break;
+
+ case mhop_atoi:
+ case mhop_itoa:
+ case mhop_printn:
+ case mhop_prints:
+ break;
+
+ default:
+ abort ();
+ }
+ }
+ if (lab[0] > 0)
+ qsort (lab + 1, lab[0], sizeof lab[0], comp_pc);
+ return lab;
+}
+
+/* Print to *PBUF (of size *PSZ) the label corresponding to the address PC.
+ If there's no label having this address (in particular, if LAB==NULL),
+ format the address itself to *PBUF.
+ Reallocate *PBUF, updating *PSZ, if necessary.
+*/
void
-mh_format_dump_disass (mh_format_t fmt)
+format_label (size_t *lab, size_t pc, char **pbuf, size_t *psz)
+{
+ size_t ln = find_label (lab, pc);
+ if (ln)
+ mu_asnprintf (pbuf, psz, "L%ld", (long) ln);
+ else
+ mu_asnprintf (pbuf, psz, "%ld", (long) pc);
+}
+
+/* Dump disassembled code of FMT to stdout. If ADDR is 0, print label names
+ where necessary, otherwise, prefix each line of output with its program
+ counter in decimal.
+*/
+void
+mh_format_dump_disass (mh_format_t fmt, int addr)
{
mh_instr_t *prog = fmt->prog;
size_t pc = 1;
@@ -1908,14 +2028,46 @@ mh_format_dump_disass (mh_format_t fmt)
[R_ACC] = "acc"
};
static char c_trans[] = "\\\\\"\"a\ab\bf\fn\nr\rt\tv\v";
+ size_t *lab;
+ size_t lc;
+ char *lbuf = NULL;
+ size_t lsz = 0;
if (!prog)
return;
+
+ if (!addr)
+ lab = extract_labels (fmt);
+ else
+ lab = NULL;
+ lc = lab ? 1 : 0;
+
while (!stop)
{
mh_opcode_t opcode;
- printf ("% 4.4ld: ", (long) pc);
+ if (addr)
+ printf ("% 4.4ld: ", (long) pc);
+ else
+ {
+ int w = 0;
+ if (lc <= lab[0] && lab[lc] == pc)
+ {
+ w = printf ("L%ld:", (long) lc);
+ lc++;
+ }
+ if (w > 8)
+ {
+ putchar ('\n');
+ w = 0;
+ }
+ while (w < 8)
+ {
+ putchar (' ');
+ w++;
+ }
+ }
+
switch (opcode = MHI_OPCODE (prog[pc++]))
{
case mhop_stop:
@@ -1926,21 +2078,24 @@ mh_format_dump_disass (mh_format_t fmt)
case mhop_branch:
{
long n = MHI_NUM (prog[pc++]);
- printf ("branch %ld", pc + n - 1);
+ format_label (lab, pc + n - 1, &lbuf, &lsz);
+ printf ("branch %s", lbuf);
}
break;
case mhop_brzn:
{
long n = MHI_NUM (prog[pc++]);
- printf ("brzn %ld", pc + n - 1);
+ format_label (lab, pc + n - 1, &lbuf, &lsz);
+ printf ("brzn %s", lbuf);
}
break;
case mhop_brzs:
{
long n = MHI_NUM (prog[pc++]);
- printf ("brzs %ld", pc + n - 1);
+ format_label (lab, pc + n - 1, &lbuf, &lsz);
+ printf ("brzs %s", lbuf);
}
break;
@@ -2049,6 +2204,8 @@ mh_format_dump_disass (mh_format_t fmt)
}
printf ("\n");
}
+ free (lbuf);
+ free (lab);
}
void
diff --git a/mh/tests/fmtcomp.at b/mh/tests/fmtcomp.at
index 687f54bfc..b0be1a20d 100644
--- a/mh/tests/fmtcomp.at
+++ b/mh/tests/fmtcomp.at
@@ -31,105 +31,105 @@ AT_CLEANUP])
FMTCOMP([literal],
[text],
[PRINT("text")
- 0001: printlit "text"
- 0006: stop
+ printlit "text"
+ stop
])
FMTCOMP([component],
[%{from}],
[PRINT(COMPONENT.from)
- 0001: ldcomp reg, "from"
- 0007: prints
- 0008: stop
+ ldcomp reg, "from"
+ prints
+ 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
+ ldcomp reg, "from"
+ fmtspec RALIGN|NOZEROPAD|NOCOMPWS, 40
+ prints
+ stop
])
FMTCOMP([function call],
[%(msg)],
[PRINT(msg())
- 0001: call msg
- 0003: printn
- 0004: stop
+ call msg
+ printn
+ 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
+ call msg
+ fmtspec NORALIGN|ZEROPAD|NOCOMPWS, 8
+ printn
+ stop
])
FMTCOMP([function call with literal argument],
[%(getenv PATH)],
[PRINT(getenv("PATH"))
- 0001: sets arg, "PATH"
- 0007: call getenv
- 0009: prints
- 0010: stop
+ sets arg, "PATH"
+ call getenv
+ prints
+ stop
])
FMTCOMP([function call with numeric argument],
[%(plus 10)],
[PRINT(plus(10))
- 0001: setn arg, 10
- 0004: call plus
- 0006: printn
- 0007: stop
+ setn arg, 10
+ call plus
+ printn
+ stop
])
FMTCOMP([function call with numeric argument and format spec],
[%08(plus 10)],
[FORMAT(NORALIGN|ZEROPAD|NOCOMPWS, 8, plus(10))
- 0001: setn arg, 10
- 0004: call plus
- 0006: fmtspec NORALIGN|ZEROPAD|NOCOMPWS, 8
- 0008: printn
- 0009: stop
+ setn arg, 10
+ call plus
+ fmtspec NORALIGN|ZEROPAD|NOCOMPWS, 8
+ printn
+ 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
+ ldcomp reg, "subject"
+ movs arg, reg
+ call decode
+ prints
+ 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
+ ldcomp reg, "subject"
+ movs arg, reg
+ call decode
+ movs arg, reg
+ call null
+ printn
+ 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
+ ldcomp reg, "subject"
+ movs arg, reg
+ call decode
+ atoi
+ movn arg, reg
+ call zero
+ printn
+ stop
])
FMTCOMP([lit],
@@ -140,26 +140,26 @@ FMTCOMP([lit],
PRINT(lit("10"))
PRINT(lit(["(comp"]))
PRINT(lit(""))
- 0001: sets reg, "string"
- 0007: prints
- 0008: sets reg, "10"
- 0013: prints
- 0014: sets reg, ["(comp"]
- 0020: prints
- 0021: sets reg, ""
- 0026: prints
- 0027: stop
+ sets reg, "string"
+ prints
+ sets reg, "10"
+ prints
+ sets reg, ["(comp"]
+ prints
+ sets reg, ""
+ prints
+ stop
])
FMTCOMP([num],
[%(num 10)%(num)],
[PRINT(num(10))
PRINT(num(0))
- 0001: setn reg, 10
- 0004: printn
- 0005: setn reg, 0
- 0008: printn
- 0009: stop
+ setn reg, 10
+ printn
+ setn reg, 0
+ printn
+ stop
])
FMTCOMP([simple conditional],
@@ -167,13 +167,13 @@ FMTCOMP([simple conditional],
[IF (COMPONENT.replied) THEN
PRINT("-")
FI
- 0001: ldcomp reg, "replied"
- 0008: brzs 16
- 0010: printlit "-"
- 0014: branch 24
- 0016: setn reg, 0
- 0019: sets reg, ""
- 0024: stop
+ ldcomp reg, "replied"
+ brzs L1
+ printlit "-"
+ branch L2
+L1: setn reg, 0
+ sets reg, ""
+L2: stop
],[],[-format])
FMTCOMP([if-else],
@@ -183,12 +183,12 @@ FMTCOMP([if-else],
ELSE
PRINT("+")
FI
- 0001: ldcomp reg, "replied"
- 0008: brzs 16
- 0010: printlit "-"
- 0014: branch 20
- 0016: printlit "+"
- 0020: stop
+ ldcomp reg, "replied"
+ brzs L1
+ printlit "-"
+ branch L2
+L1: printlit "+"
+L2: stop
])
FMTCOMP([if-elsif-else],
@@ -202,16 +202,16 @@ ELSE
PRINT(" ")
FI
FI
- 0001: ldcomp reg, "replied"
- 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
+ ldcomp reg, "replied"
+ brzs L1
+ printlit "-"
+ branch L3
+L1: ldcomp reg, "encrypted"
+ brzs L2
+ printlit "E"
+ branch L3
+L2: printlit " "
+L3: stop
])
# The example below is taken from mh-format(1), subsection
@@ -221,28 +221,28 @@ FI
FMTCOMP([inline conditional],
[%(formataddr %<{reply-to}%|%{from}%>)],
[formataddr(IF (COMPONENT.reply-to) THEN; ; ELSE PRINT(COMPONENT.from); FI)
- 0001: movs acc, reg
- 0004: ldcomp reg, "reply-to"
- 0011: brzs 15
- 0013: branch 22
- 0015: ldcomp reg, "from"
- 0021: prints
- 0022: movs arg, reg
- 0025: call formataddr
- 0027: stop
+ movs acc, reg
+ ldcomp reg, "reply-to"
+ brzs L1
+ branch L2
+L1: ldcomp reg, "from"
+ prints
+L2: movs arg, reg
+ call formataddr
+ stop
])
FMTCOMP([inline conditional (2)],
[%(formataddr %<{reply-to}%|%(void{from})%>)],
[formataddr(IF (COMPONENT.reply-to) THEN; ; ELSE COMPONENT.from; FI)
- 0001: movs acc, reg
- 0004: ldcomp reg, "reply-to"
- 0011: brzs 15
- 0013: branch 21
- 0015: ldcomp reg, "from"
- 0021: movs arg, reg
- 0024: call formataddr
- 0026: stop
+ movs acc, reg
+ ldcomp reg, "reply-to"
+ brzs L1
+ branch L2
+L1: ldcomp reg, "from"
+L2: movs arg, reg
+ call formataddr
+ stop
])
FMTCOMP([statement list],
@@ -250,17 +250,17 @@ FMTCOMP([statement list],
[formataddr(IF (COMPONENT.reply-to) THEN; ; ELSE COMPONENT.from; FI)
width()
putaddr("To: ")
- 0001: movs acc, reg
- 0004: ldcomp reg, "reply-to"
- 0011: brzs 15
- 0013: branch 21
- 0015: ldcomp reg, "from"
- 0021: movs arg, reg
- 0024: call formataddr
- 0026: call width
- 0028: sets arg, "To: "
- 0034: call putaddr
- 0036: stop
+ movs acc, reg
+ ldcomp reg, "reply-to"
+ brzs L1
+ branch L2
+L1: ldcomp reg, "from"
+L2: movs arg, reg
+ call formataddr
+ call width
+ sets arg, "To: "
+ call putaddr
+ stop
])
m4_popdef[FMTCOMP])

Return to:

Send suggestions and report system problems to the System administrator.