diff --git a/Makefile b/Makefile index 8716326..eb6b86c 100644 --- a/Makefile +++ b/Makefile @@ -55,8 +55,8 @@ install: mspdebug mspdebug.man mspdebug: main.o fet.o rf2500.o dis.o uif.o olimex.o ihex.o elf32.o stab.o \ util.o bsl.o sim.o symmap.o gdb.o btree.o rtools.o sym.o devcmd.o \ - cproc.o vector.o cproc_util.o expr.o fet_error.o binfile.o fet_db.o \ - usbutil.o titext.o srec.o device.o coff.o opdb.o + cproc.o vector.o output_util.o expr.o fet_error.o binfile.o \ + fet_db.o usbutil.o titext.o srec.o device.o coff.o opdb.o output.o $(CC) $(LDFLAGS) $(MACPORTS_LDFLAGS) -o $@ $^ -lusb $(READLINE_LIBS) .c.o: diff --git a/cproc.c b/cproc.c index fb54b1a..e2b0c42 100644 --- a/cproc.c +++ b/cproc.c @@ -34,6 +34,7 @@ #include "vector.h" #include "stab.h" #include "util.h" +#include "output.h" struct cproc { struct vector command_list; @@ -150,16 +151,14 @@ static int cmd_help(cproc_t cp, char **arg) struct opdb_key key; if (cmd) { - cproc_printf(cp, "\x1b[1mCOMMAND: %s\x1b[0m\n", - cmd->name); - fputs(cmd->help, stdout); + printc("\x1b[1mCOMMAND: %s\x1b[0m\n\n%s\n", + cmd->name, cmd->help); return 0; } if (!opdb_get(topic, &key, NULL)) { - cproc_printf(cp, "\x1b[1mOPTION: %s (%s)\x1b[0m\n", - key.name, type_text(key.type)); - fputs(key.help, stdout); + printc("\x1b[1mOPTION: %s (%s)\x1b[0m\n\n%s\n", + key.name, type_text(key.type), key.help); return 0; } @@ -343,39 +342,6 @@ int cproc_register_commands(cproc_t cp, const struct cproc_command *cmd, return 0; } -void cproc_printf(cproc_t cp, const char *fmt, ...) -{ - char buf[256]; - va_list ap; - - va_start(ap, fmt); - vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - - if (!opdb_get_boolean("color")) { - char *src = buf; - char *dst = buf; - - for (;;) { - if (*src == 27) { - while (*src && !isalpha(*src)) - src++; - if (*src) - src++; - } - - if (!*src) - break; - - *(dst++) = *(src++); - } - - *dst = 0; - } - - puts(buf); -} - void cproc_modify(cproc_t cp, int flags) { cp->modify_flags |= flags; diff --git a/cproc.h b/cproc.h index e87c2da..3398a4c 100644 --- a/cproc.h +++ b/cproc.h @@ -71,13 +71,6 @@ void cproc_destroy(cproc_t cp); int cproc_register_commands(cproc_t cp, const struct cproc_command *cmd, int count); -/* Print a line of text on the command processor's standard output. - * - * ANSI colour codes can be embedded in the output text, and will be stripped - * out if colour is disabled. - */ -void cproc_printf(cproc_t cp, const char *fmt, ...); - /* This should be called before a destructive operation to give the user * a chance to abort. If it returns 1, then the operation should be aborted. * diff --git a/devcmd.c b/devcmd.c index 8bb46b2..1039ae7 100644 --- a/devcmd.c +++ b/devcmd.c @@ -27,7 +27,7 @@ #include "stab.h" #include "expr.h" #include "cproc.h" -#include "cproc_util.h" +#include "output_util.h" #include "util.h" #include "dis.h" @@ -39,7 +39,7 @@ static int cmd_regs(cproc_t cp, char **arg) if (device_default->getregs(device_default, regs) < 0) return -1; - cproc_regs(cp, regs); + show_regs(regs); /* Try to disassemble the instruction at PC */ if (len > 0x10000 - regs[0]) @@ -47,7 +47,7 @@ static int cmd_regs(cproc_t cp, char **arg) if (device_default->readmem(device_default, regs[0], code, len) < 0) return 0; - cproc_disassemble(cp, regs[0], (uint8_t *)code, len); + disassemble(regs[0], (uint8_t *)code, len); return 0; } @@ -85,7 +85,7 @@ static int cmd_md(cproc_t cp, char **arg) if (device_default->readmem(device_default, offset, buf, blen) < 0) return -1; - cproc_hexdump(cp, offset, buf, blen); + hexdump(offset, buf, blen); offset += blen; length -= blen; @@ -240,7 +240,7 @@ static int cmd_set(cproc_t cp, char **arg) if (device_default->setregs(device_default, regs) < 0) return -1; - cproc_regs(cp, regs); + show_regs(regs); return 0; } @@ -284,7 +284,7 @@ static int cmd_dis(cproc_t cp, char **arg) return -1; } - cproc_disassemble(cp, offset, buf, length); + disassemble(offset, buf, length); free(buf); return 0; } diff --git a/output.c b/output.c new file mode 100644 index 0000000..63a94d3 --- /dev/null +++ b/output.c @@ -0,0 +1,68 @@ +/* MSPDebug - debugging tool for MSP430 MCUs + * Copyright (C) 2009, 2010 Daniel Beer + * + * 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 2 of the License, 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include "opdb.h" +#include "output.h" + +static char out_buf[1024]; +static int out_len; +static int in_code; + +static int write_text(const char *buf) +{ + int want_color = opdb_get_boolean("color"); + int len = 0; + + while (*buf) { + if (*buf == 27) + in_code = 1; + + if (!in_code) + len++; + + if (*buf == '\n') { + out_buf[out_len] = 0; + puts(out_buf); + out_len = 0; + } else if ((want_color || !in_code) && + out_len + 1 < sizeof(out_buf)) { + out_buf[out_len++] = *buf; + } + + if (isalpha(*buf)) + in_code = 0; + + buf++; + } + + return len; +} + +int printc(const char *fmt, ...) +{ + char buf[1024]; + va_list ap; + + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + + return write_text(buf); +} diff --git a/output.h b/output.h new file mode 100644 index 0000000..d8f3c55 --- /dev/null +++ b/output.h @@ -0,0 +1,30 @@ +/* MSPDebug - debugging tool for MSP430 MCUs + * Copyright (C) 2009, 2010 Daniel Beer + * + * 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 2 of the License, 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef OUTPUT_H_ +#define OUTPUT_H_ + +/* Print output. ANSI colour codes may be embedded, and these will be + * stripped on output if colour output is disabled. + * + * Returns the number of characters printed (not including colour + * codes). + */ +int printc(const char *fmt, ...); + +#endif diff --git a/cproc_util.c b/output_util.c similarity index 55% rename from cproc_util.c rename to output_util.c index f929832..6bbb36c 100644 --- a/cproc_util.c +++ b/output_util.c @@ -20,12 +20,11 @@ #include #include "dis.h" -#include "cproc_util.h" +#include "output_util.h" #include "stab.h" #include "util.h" -static int format_addr(char *buf, int max_len, - msp430_amode_t amode, uint16_t addr) +static int format_addr(msp430_amode_t amode, uint16_t addr) { char name[64]; address_t offset; @@ -56,18 +55,14 @@ static int format_addr(char *buf, int max_len, (addr >= 0x200 && addr < 0xfff0)) && !stab_nearest(stab_default, addr, name, sizeof(name), &offset) && !offset) - return snprintf(buf, max_len, - "%s\x1b[1m%s\x1b[0m", prefix, name); + return printc("%s\x1b[1m%s\x1b[0m", prefix, name); else if (numeric) - return snprintf(buf, max_len, - "%s\x1b[1m0x%x\x1b[0m", prefix, addr); + return printc("%s\x1b[1m0x%x\x1b[0m", prefix, addr); else - return snprintf(buf, max_len, - "%s\x1b[1m0x%04x\x1b[0m", prefix, addr); + return printc("%s\x1b[1m0x%04x\x1b[0m", prefix, addr); } -static int format_reg(char *buf, int max_len, - msp430_amode_t amode, msp430_reg_t reg) +static int format_reg(msp430_amode_t amode, msp430_reg_t reg) { const char *prefix = ""; const char *suffix = ""; @@ -98,9 +93,7 @@ static int format_reg(char *buf, int max_len, if (!name) name = "???"; - return snprintf(buf, max_len, - "%s\x1b[33m%s\x1b[0m%s", - prefix, name, suffix); + return printc("%s\x1b[33m%s\x1b[0m%s", prefix, name, suffix); } /* Given an operands addressing mode, value and associated register, @@ -108,24 +101,21 @@ static int format_reg(char *buf, int max_len, * * Returns the number of characters printed. */ -static int format_operand(char *buf, int max_len, - msp430_amode_t amode, uint16_t addr, +static int format_operand(msp430_amode_t amode, uint16_t addr, msp430_reg_t reg) { int len = 0; - len += format_addr(buf, max_len, amode, addr); - len += format_reg(buf + len, max_len - len, amode, reg); + len += format_addr(amode, addr); + len += format_reg(amode, reg); + return len; } /* Write assembly language for the instruction to this buffer */ -static int dis_format(char *buf, int max_len, - const struct msp430_instruction *insn) +static int dis_format(const struct msp430_instruction *insn) { - int len; - int tlen; - int total = 0; + int len = 0; const char *opname = dis_opcode_name(insn->op); const char *suffix = ""; @@ -145,67 +135,38 @@ static int dis_format(char *buf, int max_len, insn->op == MSP430_OP_BRA || insn->op == MSP430_OP_RETA) suffix = ""; - len = snprintf(buf + total, max_len - total, - "\x1b[36m%s%s\x1b[0m", opname, suffix); - tlen = textlen(buf + total); - total += len; - - while (tlen < 8 && total < max_len) { - buf[total++] = ' '; - tlen++; - } + len += printc("\x1b[36m%s%s\x1b[0m", opname, suffix); + while (len < 8) + len += printc(" "); /* Source operand */ if (insn->itype == MSP430_ITYPE_DOUBLE) { - len = format_operand(buf + total, - max_len - total, - insn->src_mode, - insn->src_addr, - insn->src_reg); - tlen = textlen(buf + total); - total += len; + len += format_operand(insn->src_mode, + insn->src_addr, + insn->src_reg); - if (total < max_len) - buf[total++] = ','; - - while (tlen < 15 && total < max_len) { - tlen++; - buf[total++] = ' '; - } - - if (total < max_len) - buf[total++] = ' '; + printc(","); + while (len < 15) + len += printc(" "); + printc(" "); } /* Destination operand */ if (insn->itype != MSP430_ITYPE_NOARG) - total += format_operand(buf + total, - max_len - total, - insn->dst_mode, + len += format_operand(insn->dst_mode, insn->dst_addr, insn->dst_reg); /* Repetition count */ if (insn->rep_register) - total += snprintf(buf + total, max_len - total, - " [repeat %s]", - dis_reg_name(insn->rep_index)); + len += printc(" [repeat %s]", dis_reg_name(insn->rep_index)); else if (insn->rep_index) - total += snprintf(buf + total, max_len - total, - " [repeat %d]", insn->rep_index + 1); + len += printc(" [repeat %d]", insn->rep_index + 1); - if (total < max_len) - buf[total] = 0; - else if (total) { - total--; - buf[total] = 0; - } - - return total; + return len; } -void cproc_disassemble(cproc_t cp, - address_t offset, const uint8_t *data, int length) +void disassemble(address_t offset, const uint8_t *data, int length) { int first_line = 1; @@ -216,16 +177,14 @@ void cproc_disassemble(cproc_t cp, int i; address_t oboff; char obname[64]; - char buf[256]; - int len = 0; if (!stab_nearest(stab_default, offset, obname, sizeof(obname), &oboff)) { if (!oboff) - cproc_printf(cp, "\x1b[m%s:\x1b[0m", obname); + printc("\x1b[m%s:\x1b[0m\n", obname); else if (first_line) - cproc_printf(cp, "\x1b[m%s+0x%x:\x1b[0m", - obname, oboff); + printc("\x1b[m%s+0x%x:\x1b[0m\n", + obname, oboff); } first_line = 0; @@ -234,92 +193,72 @@ void cproc_disassemble(cproc_t cp, if (count > length) count = length; - len += snprintf(buf + len, sizeof(buf) - len, - " \x1b[36m%05x\x1b[0m:", offset); + printc(" \x1b[36m%05x\x1b[0m:", offset); for (i = 0; i < count; i++) - len += snprintf(buf + len, sizeof(buf) - len, - " %02x", data[i]); + printc(" %02x", data[i]); while (i < 9) { - buf[len++] = ' '; - buf[len++] = ' '; - buf[len++] = ' '; + printc(" "); i++; } if (retval >= 0) - len += dis_format(buf + len, sizeof(buf) - len, - &insn); + dis_format(&insn); + printc("\n"); - buf[len] = 0; - cproc_printf(cp, "%s", buf); offset += count; length -= count; data += count; } } -void cproc_hexdump(cproc_t cp, address_t addr, const uint8_t *data, int data_len) +void hexdump(address_t addr, const uint8_t *data, int data_len) { int offset = 0; while (offset < data_len) { - char buf[128]; - int len = 0; int i, j; /* Address label */ - len += snprintf(buf + len, sizeof(buf) - len, - " \x1b[36m%05x:\x1b[0m", offset + addr); + printc(" \x1b[36m%05x:\x1b[0m", offset + addr); /* Hex portion */ for (i = 0; i < 16 && offset + i < data_len; i++) - len += snprintf(buf + len, sizeof(buf) - len, - " %02x", data[offset + i]); - for (j = i; j < 16; j++) { - buf[len++] = ' '; - buf[len++] = ' '; - buf[len++] = ' '; - } + printc(" %02x", data[offset + i]); + for (j = i; j < 16; j++) + printc(" "); /* Printable characters */ - len += snprintf(buf + len, sizeof(buf) - len, - " \x1b[32m|"); + printc(" \x1b[32m|"); for (j = 0; j < i; j++) { int c = data[offset + j]; - buf[len++] = (c >= 32 && c <= 126) ? c : '.'; + printc("%c", (c >= 32 && c <= 126) ? c : '.'); } for (; j < 16; j++) - buf[len++] = ' '; - len += snprintf(buf + len, sizeof(buf) - len, - "|\x1b[0m"); + printc(" "); + printc("|\x1b[0m\n"); - cproc_printf(cp, "%s", buf); offset += i; } } -void cproc_regs(cproc_t cp, const address_t *regs) +void show_regs(const address_t *regs) { int i; for (i = 0; i < 4; i++) { int j; - char buf[128]; - int len = 0; - for (j = 0; j < 4; j++) - buf[len++] = ' '; + printc(" "); for (j = 0; j < 4; j++) { int k = j * 4 + i; - len += snprintf(buf + len, sizeof(buf) - len, - "(\x1b[1m%3s:\x1b[0m %05x) ", - dis_reg_name(k), regs[k]); + printc("(\x1b[1m%3s:\x1b[0m %05x) ", + dis_reg_name(k), regs[k]); } - cproc_printf(cp, "%s", buf); + printc("\n"); } } diff --git a/cproc_util.h b/output_util.h similarity index 75% rename from cproc_util.h rename to output_util.h index b3cba05..fa4c952 100644 --- a/cproc_util.h +++ b/output_util.h @@ -16,21 +16,19 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef CPROC_UTIL_H_ -#define CPROC_UTIL_H_ +#ifndef OUTPUT_UTIL_H_ +#define OUTPUT_UTIL_H_ -#include -#include "cproc.h" +#include "output.h" +#include "util.h" /* Print colorized disassembly on command processor standard output */ -void cproc_disassemble(cproc_t cp, address_t addr, - const uint8_t *buf, int len); +void disassemble(address_t addr, const uint8_t *buf, int len); /* Print colorized hexdump on standard output */ -void cproc_hexdump(cproc_t cp, address_t addr, - const uint8_t *buf, int len); +void hexdump(address_t addr, const uint8_t *buf, int len); /* Colorized register dump */ -void cproc_regs(cproc_t cp, const address_t *regs); +void show_regs(const address_t *regs); #endif diff --git a/rtools.c b/rtools.c index ee5587f..f28d4ed 100644 --- a/rtools.c +++ b/rtools.c @@ -28,7 +28,7 @@ #include "rtools.h" #include "stab.h" #include "expr.h" -#include "cproc_util.h" +#include "output_util.h" #include "vector.h" /************************************************************************ @@ -366,7 +366,7 @@ static int do_isearch(cproc_t cp, address_t addr, address_t len, int count = dis_decode(mbuf + i, addr + i, len - i, &insn); if (count >= 0 && isearch_match(&insn, q)) - cproc_disassemble(cp, addr + i, mbuf + i, count); + disassemble(addr + i, mbuf + i, count); } free(mbuf);