diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4505ef1b..c10a77eb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -228,6 +228,7 @@ add_library(libavrdude strutil.c teensy.c teensy.h + term.c tpi.h updi_constants.h updi_link.c @@ -292,8 +293,6 @@ target_link_libraries(libavrdude add_executable(avrdude main.c - term.c - term.h developer_opts.c developer_opts.h developer_opts_private.h diff --git a/src/Makefile.am b/src/Makefile.am index 5f9c97db..9ac585a5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -175,6 +175,7 @@ libavrdude_a_SOURCES = \ strutil.c \ teensy.c \ teensy.h \ + term.c \ tpi.h \ usbasp.c \ usbasp.h \ @@ -214,9 +215,7 @@ avrdude_SOURCES = \ whereami.h \ developer_opts.c \ developer_opts.h \ - developer_opts_private.h \ - term.c \ - term.h + developer_opts_private.h man_MANS = avrdude.1 diff --git a/src/avrdude.1 b/src/avrdude.1 index 8ed9e8f1..9594a07e 100644 --- a/src/avrdude.1 +++ b/src/avrdude.1 @@ -44,6 +44,7 @@ .Op Fl O .Op Fl P Ar port .Op Fl q +.Op Fl T Ar cmd .Op Fl t .Op Fl U Ar memtype:op:filename:filefmt .Op Fl v @@ -694,17 +695,28 @@ to the device. Specify it more often for even quieter operations. .It Fl s, u These options used to control the obsolete "safemode" feature which is no longer present. They are silently ignored for backwards compatibility. +.It Fl T Ar cmd +Slots a terminal command line +.Ar cmd +into the intermixed list of -T terminal commands and -U memory operations. +The terminal command line is executed when it is its turn in the mixed list. +Except for the simplest of terminal commands the argument +.Ar cmd +will most likely need to be set in quotes, see your OS shell manual for +details. .It Fl t Tells .Nm -to enter the interactive ``terminal'' mode instead of up- or downloading -files. See below for a detailed description of the terminal mode. +to enter the interactive terminal shell before up- or downloading files +via the -U option or processing other -T terminal commands, if any. See +below for a detailed description of the terminal mode. .It Xo Fl U Ar memtype Ns .Ar \&: Ns Ar op Ns .Ar \&: Ns Ar filename Ns .Op \&: Ns Ar format .Xc -Perform a memory operation as indicated. The +Perform a memory operation as indicated. Multiple -U operations are +allowed. The .Ar memtype field specifies the memory type to operate on. The available memory types are device-dependent, the actual diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index d3ac921d..ce6afba0 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -757,9 +757,17 @@ to the device. Specify it a second time for even quieter operation. These options used to control the obsolete "safemode" feature which is no longer present. They are silently ignored for backwards compatibility. +@item -T @var{cmd} +Slots a terminal command line @var{cmd} into the intermixed list of +@code{-T} terminal commands and @code{-U} memory operations. The terminal +command line is executed when it is its turn in the mixed list. Except for +the simplest of terminal commands the argument @var{cmd} will most likely +need to be set in quotes, see your OS shell manual for details. + @item -t -Tells AVRDUDE to enter the interactive ``terminal'' mode instead of up- -or downloading files. See below for a detailed description of the +Tells AVRDUDE to enter the interactive terminal shell before uploading or +downloading files via the @code{-U} option or processing other @code{-T} +terminal commands, if any. See below for a detailed description of the terminal mode. @item -U @var{memtype}:@var{op}:@var{filename}[:@var{format}] @@ -2563,6 +2571,66 @@ avrdude done. Thank you. @end cartouche @end smallexample +@page + +@noindent +@strong{Mixing terminal commands and @code{-U} memory operations:} the +example below burns a bootloader, uses a terminal line to write +application data to flash, loads the application, configures the brownout +detection level to 2.7 V and, finally, stores the full flash as new hex +file. Note the use of different quotation marks in @code{bash} to pass the +terminal command lines as single entity to AVRDUDE. + +@smallexample +@cartouche + +$ avrdude -qc dryrun -p m328p \ + -U urboot_m328p_1s_autobaud_uart0_pr_ee_ce.hex \ + -T 'write flash 0x7D00 0xc0cac01a 0xcafe "secret Coca Cola recipe"' \ + -U flash:w:cola-vending-machine.hex \ + -T "config -v bod=*2v7" \ + -U flash:r:app+data.hex:I + +avrdude: AVR device initialized and ready to accept instructions +avrdude: device signature = 0x1e950f (probably m328p) +avrdude: Note: flash memory has been specified, an erase cycle will be performed. + To disable this feature, specify the -D option. +avrdude: erasing chip + +avrdude: processing -U flash:w:urboot_m328p_1s_autobaud_uart0_pr_ee_ce.hex:i +avrdude: reading input file urboot_m328p_1s_autobaud_uart0_pr_ee_ce.hex for flash + with 368 bytes in 2 sections within [0x7e80, 0x7fff] + using 3 pages and 16 pad bytes +avrdude: writing 368 bytes flash ... +avrdude: 368 bytes of flash written +avrdude: verifying flash memory against urboot_m328p_1s_autobaud_uart0_pr_ee_ce.hex +avrdude: 368 bytes of flash verified + +avrdude: processing -T write flash 0x7D00 0xc0cac01a 0xcafe "secret Coca Cola recipe" +avrdude: synching cache to device ... done + +avrdude: processing -U flash:w:cola-vending-machine.hex:i +avrdude: reading input file cola-vending-machine.hex for flash + with 736 bytes in 1 section within [0, 0x2df] + using 6 pages and 32 pad bytes +avrdude: writing 736 bytes flash ... +avrdude: 736 bytes of flash written +avrdude: verifying flash memory against cola-vending-machine.hex +avrdude: 736 bytes of flash verified + +avrdude: processing -T config -v bod=*2v7 +config bodlevel=bod_2v7 # 5 + +avrdude: processing -U flash:r:app+data.hex:I +avrdude: reading flash memory ... +avrdude: writing output file app+data.hex + +avrdude done. Thank you. + +@end cartouche +@end smallexample + + @page @c diff --git a/src/fileio.c b/src/fileio.c index 75facd55..0dcf95d5 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -130,7 +130,36 @@ char *fileio_fmtstr(FILEFMT format) { return "octal byte list"; default: return "invalid format"; - }; + } +} + +int fileio_fmtchr(FILEFMT format) { + switch (format) { + case FMT_AUTO: + return 'a'; + case FMT_SREC: + return 's'; + case FMT_IHEX: + return 'i'; + case FMT_IHXC: + return 'I'; + case FMT_RBIN: + return 'r'; + case FMT_ELF: + return 'e'; + case FMT_IMM: + return 'm'; + case FMT_BIN: + return 'b'; + case FMT_DEC: + return 'd'; + case FMT_HEX: + return 'h'; + case FMT_OCT: + return 'o'; + default: + return '?'; + } } diff --git a/src/libavrdude.h b/src/libavrdude.h index e16810dd..44ae0f7c 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -1020,6 +1020,8 @@ FILEFMT fileio_format(char c); char *fileio_fmtstr(FILEFMT format); +int fileio_fmtchr(FILEFMT format); + FILE *fileio_fopenr(const char *fname); int fileio_fmt_autodetect_fp(FILE *f); @@ -1051,10 +1053,11 @@ enum updateflags { typedef struct update_t { - char * memtype; - int op; - char * filename; - int format; + const char *cmdline; // -T line is stored here and takes precedence if it exists + char *memtype; // Memory name for -U + int op; // Symbolic memory operation DEVICE_... for -U + char *filename; // Filename for -U, can be - + int format; // File format FMT_... } UPDATE; typedef struct { // File reads for flash can exclude trailing 0xff, which are cut off @@ -1072,21 +1075,15 @@ typedef struct { // File reads for flash can exclude trailing 0xf extern "C" { #endif -extern UPDATE * parse_op(char * s); -extern UPDATE * dup_update(UPDATE * upd); -extern UPDATE * new_update(int op, char * memtype, int filefmt, - char * filename); -extern void free_update(UPDATE * upd); -extern int do_op(const PROGRAMMER *pgm, const AVRPART *p, UPDATE *upd, - enum updateflags flags); - -extern int memstats(const AVRPART *p, const char *memtype, int size, Filestats *fsp); - -// Convenience functions for printing -const char *update_plural(int x); -const char *update_inname(const char *fn); -const char *update_outname(const char *fn); -const char *update_interval(int a, int b); +UPDATE *parse_op(const char *s); +UPDATE *dup_update(const UPDATE *upd); +UPDATE *new_update(int op, const char *memstr, int filefmt, const char *fname); +UPDATE *cmd_update(const char *cmd); +extern void free_update(UPDATE *upd); +char *update_str(const UPDATE *upd); +int do_op(const PROGRAMMER *pgm, const AVRPART *p, const UPDATE *upd, + enum updateflags flags); +int memstats(const AVRPART *p, const char *memtype, int size, Filestats *fsp); // Helper functions for dry run to determine file access int update_is_okfile(const char *fn); @@ -1235,6 +1232,10 @@ char *str_uc(char *s); char *str_lcfirst(char *s); char *str_ucfirst(char *s); char *str_utoa(unsigned n, char *buf, int base); +const char *str_plural(int x); +const char *str_inname(const char *fn); +const char *str_outname(const char *fn); +const char *str_interval(int a, int b); bool is_bigendian(); void change_endian(void *p, int size); int memall(const void *p, char c, size_t n); @@ -1245,6 +1246,12 @@ unsigned long long int str_int(const char *str, int type, const char **errpp); int str_membuf(const char *str, int type, unsigned char *buf, int size, const char **errpp); char *str_nexttok(char *buf, const char *delim, char **next); +int terminal_mode(const PROGRAMMER *pgm, const AVRPART *p); +int terminal_mode_noninteractive(const PROGRAMMER *pgm, const AVRPART *p); +int terminal_line(const PROGRAMMER *pgm, const AVRPART *p, const char *line); +char *terminal_get_input(const char *prompt); +void terminal_setup_update_progress(); + #ifdef __cplusplus } #endif diff --git a/src/main.c b/src/main.c index ee99d1ff..36e5cdbe 100644 --- a/src/main.c +++ b/src/main.c @@ -49,7 +49,6 @@ #include "avrdude.h" #include "libavrdude.h" #include "config.h" -#include "term.h" #include "developer_opts.h" /* Get VERSION from ac_cfg.h */ @@ -225,34 +224,35 @@ static void usage(void) msg_error( "Usage: %s [options]\n" "Options:\n" - " -p Specify AVR device\n" - " -p / Run developer options for matched AVR devices\n" - " -b Override RS-232 baud rate\n" - " -B Specify bit clock period (us)\n" - " -C Specify location of configuration file\n" - " -c Specify programmer type\n" - " -c / Run developer options for matched programmers\n" - " -A Disable trailing-0xff removal from file and AVR read\n" - " -D Disable auto erase for flash memory; implies -A\n" - " -i ISP Clock Delay [in microseconds]\n" - " -P Specify connection port\n" - " -F Override invalid signature or initialisation check\n" - " -e Perform a chip erase\n" - " -O Perform RC oscillator calibration (see AVR053)\n" + " -p Specify AVR device\n" + " -p / Run developer options for matched AVR devices\n" + " -b Override RS-232 baud rate\n" + " -B Specify bit clock period (us)\n" + " -C Specify location of configuration file\n" + " -c Specify programmer type\n" + " -c / Run developer options for matched programmers\n" + " -A Disable trailing-0xff removal for file/AVR read\n" + " -D Disable auto erase for flash memory; implies -A\n" + " -i ISP Clock Delay [in microseconds]\n" + " -P Specify connection port\n" + " -F Override invalid signature or initial checks\n" + " -e Perform a chip erase\n" + " -O Perform RC oscillator calibration (see AVR053)\n" + " -t Enter terminal shell before processing -U/T\n" + " -T Slot terminal line into a list and run in turn\n" " -U :r|w|v:[:format]\n" - " Memory operation specification\n" - " Multiple -U options are allowed, each request\n" - " is performed in the order specified\n" - " -n Do not write to the device whilst processing -U\n" - " -V Do not automatically verify during -U\n" - " -t Enter terminal mode\n" - " -E [,] List programmer exit specifications\n" - " -x Pass to programmer, see -xhelp\n" - " -v Verbose output; -v -v for more\n" - " -q Quell progress output; -q -q for less\n" - " -l logfile Use logfile rather than stderr for diagnostics\n" - " -? Display this usage\n" - "\navrdude version %s, URL: \n", + " Memory operation specification\n" + " Multiple -U/T options are allowed; each request\n" + " is performed in the specified intermixed order\n" + " -n Do not write to the device whilst processing -U\n" + " -V Do not automatically verify during -U\n" + " -E [,] List programmer exit specifications\n" + " -x Pass to programmer, see -xhelp\n" + " -v Verbose output; -v -v for more\n" + " -q Quell progress output; -q -q for less\n" + " -l logfile Use logfile rather than stderr for diagnostics\n" + " -? Display this usage\n" + "\navrdude version %s, https://github.com/avrdudes/avrdude\n", progname, version); } @@ -632,7 +632,7 @@ int main(int argc, char * argv []) /* * process command line arguments */ - while ((ch = getopt(argc,argv,"?Ab:B:c:C:DeE:Fi:l:np:OP:qstU:uvVx:yY:")) != -1) { + while ((ch = getopt(argc,argv,"?Ab:B:c:C:DeE:Fi:l:np:OP:qstT:U:uvVx:yY:")) != -1) { switch (ch) { case 'b': /* override default programmer baud rate */ @@ -772,6 +772,10 @@ int main(int argc, char * argv []) pmsg_error("\"safemode\" feature no longer supported\n"); break; + case 'T': + ladd(updates, cmd_update(optarg)); + break; + case 'U': upd = parse_op(optarg); if (upd == NULL) { @@ -1235,7 +1239,7 @@ int main(int argc, char * argv []) int doexit = 0; for (ln=lfirst(updates); ln; ln=lnext(ln)) { upd = ldata(ln); - if (upd->memtype == NULL) { + if (upd->memtype == NULL && upd->cmdline == NULL) { const char *mtype = p->prog_modes & PM_PDI? "application": "flash"; pmsg_notice2("defaulting memtype in -U %c:%s option to \"%s\"\n", (upd->op == DEVICE_READ)? 'r': (upd->op == DEVICE_WRITE)? 'w': 'v', @@ -1445,6 +1449,8 @@ int main(int argc, char * argv []) uflags &= ~UF_AUTO_ERASE; for (ln=lfirst(updates); ln; ln=lnext(ln)) { upd = ldata(ln); + if(!upd->memtype) + continue; m = avr_locate_mem(p, upd->memtype); if (m == NULL) continue; @@ -1495,8 +1501,16 @@ int main(int argc, char * argv []) } + int wrmem = 0; for (ln=lfirst(updates); ln; ln=lnext(ln)) { upd = ldata(ln); + if(upd->cmdline && wrmem) { // Invalidate cache if device was written to + wrmem = 0; + pgm->reset_cache(pgm, p); + } else if(!upd->cmdline) { // Flush cache before any device memory access + pgm->flush_cache(pgm, p); + wrmem |= upd->op == DEVICE_WRITE; + } rc = do_op(pgm, p, upd, uflags); if (rc && rc != LIBAVRDUDE_SOFTFAIL) { exitrc = 1; @@ -1504,6 +1518,7 @@ int main(int argc, char * argv []) } else if(rc == 0 && upd->op == DEVICE_WRITE && avr_memtype_is_flash_type(upd->memtype)) ce_delayed = 0; // Redeemed chip erase promise } + pgm->flush_cache(pgm, p); main_exit: diff --git a/src/strutil.c b/src/strutil.c index 8bd79e52..7fa8cd9a 100644 --- a/src/strutil.c +++ b/src/strutil.c @@ -298,6 +298,39 @@ char *str_utoa(unsigned n, char *buf, int base) { } +// Convenience functions for printing +const char *str_plural(int x) { + return x==1? "": "s"; +} + +const char *str_inname(const char *fn) { + return !fn? "???": strcmp(fn, "-")? fn: ""; +} + +const char *str_outname(const char *fn) { + return !fn? "???": strcmp(fn, "-")? fn: ""; +} + +// Return sth like "[0, 0x1ff]" +const char *str_interval(int a, int b) { + // Cyclic buffer for 20+ temporary interval strings each max 41 bytes at 64-bit int + static char space[20*41 + 80], *sp; + if(!sp || sp-space > (int) sizeof space - 80) + sp = space; + + char *ret = sp; + + sprintf(sp, a<16? "[%d": "[0x%x", a); + sp += strlen(sp); + sprintf(sp, b<16? ", %d]": ", 0x%x]", b); + + // Advance beyond return string in temporary ring buffer + sp += strlen(sp)+1; + + return ret; +} + + bool is_bigendian() { union {char a[2]; int16_t i;} u = {.i = 1}; return u.a[1] == 1; diff --git a/src/term.c b/src/term.c index 7e59df5d..91d098a3 100644 --- a/src/term.c +++ b/src/term.c @@ -56,37 +56,36 @@ #include "avrdude.h" -#include "term.h" struct command { char *name; - int (*func)(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); + int (*func)(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); size_t fnoff; char *desc; }; -static int cmd_dump (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_write (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_flush (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_abort (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_erase (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_pgerase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_config (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_sig (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_part (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_help (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_quit (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_send (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_parms (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_vtarg (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_varef (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_fosc (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_sck (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_spi (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_pgm (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_verbose(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_quell (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); +static int cmd_dump (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_write (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_flush (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_abort (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_erase (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_pgerase(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_config (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_sig (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_part (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_help (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_quit (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_send (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_parms (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_vtarg (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_varef (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_fosc (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_sck (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_spi (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_pgm (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_verbose(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_quell (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); #define _fo(x) offsetof(PROGRAMMER, x) @@ -172,7 +171,7 @@ static int chardump_line(char *buffer, unsigned char *p, int n, int pad) { } -static int hexdump_buf(FILE *f, AVRMEM *m, int startaddr, unsigned char *buf, int len) { +static int hexdump_buf(const FILE *f, const AVRMEM *m, int startaddr, const unsigned char *buf, int len) { char dst1[80]; char dst2[80]; @@ -199,11 +198,11 @@ static int hexdump_buf(FILE *f, AVRMEM *m, int startaddr, unsigned char *buf, in } -static int cmd_dump(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_dump(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { static struct mem_addr_len { int addr; int len; - AVRMEM *mem; + const AVRMEM *mem; } read_mem[32]; static int i; const char *cmd = tolower(**argv) == 'd'? "dump": "read"; @@ -233,7 +232,7 @@ static int cmd_dump(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { memtype = argv[1]; else memtype = (char*)read_mem[i].mem->desc; - AVRMEM *mem = avr_locate_mem(p, memtype); + const AVRMEM *mem = avr_locate_mem(p, memtype); if (mem == NULL) { pmsg_error("(%s) %s memory type not defined for part %s\n", cmd, memtype, p->desc); return -1; @@ -363,8 +362,12 @@ static size_t maxstrlen(int argc, char **argv) { return max; } +typedef enum { + WRITE_MODE_STANDARD = 0, + WRITE_MODE_FILL = 1, +} Write_mode_t; -static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_write(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { if (argc < 3 || (argc > 1 && str_eq(argv[1], "-?"))) { msg_error( "Syntax: write [,] {[,]}\n" @@ -419,7 +422,7 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { int start_offset; // Which argc argument int len; // Number of bytes to write to memory char *memtype = argv[1]; // Memory name string - AVRMEM *mem = avr_locate_mem(p, memtype); + const AVRMEM *mem = avr_locate_mem(p, memtype); if (mem == NULL) { pmsg_error("(write) %s memory type not defined for part %s\n", memtype, p->desc); return -1; @@ -575,7 +578,7 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { if(write_mode == WRITE_MODE_FILL) { if(recorded < len) { pmsg_warning("(write ...) can only fill %d < %d byte%s as last item has zero bytes\n", - recorded, len, update_plural(recorded)); + recorded, len, str_plural(recorded)); len = recorded; } bytes_grown = 0; @@ -585,7 +588,7 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } pmsg_notice2("(write) writing %d byte%s starting from address 0x%02x", - len + bytes_grown, update_plural(len + bytes_grown), addr); + len + bytes_grown, str_plural(len + bytes_grown), addr); if (write_mode == WRITE_MODE_FILL && filling) msg_notice2("; remaining space filled with %s", argv[argc - 2]); msg_notice2("\v"); @@ -632,7 +635,7 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } -static int cmd_flush(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_flush(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { if(argc > 1) { msg_error( "Syntax: flush\n" @@ -646,7 +649,7 @@ static int cmd_flush(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } -static int cmd_abort(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_abort(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { if(argc > 1) { msg_error( "Syntax: abort\n" @@ -660,7 +663,7 @@ static int cmd_abort(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } -static int cmd_send(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_send(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { unsigned char cmd[4], res[4]; const char *errptr; int i; @@ -713,7 +716,7 @@ static int cmd_send(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } -static int cmd_erase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_erase(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { if (argc > 4 || argc == 3 || (argc > 1 && str_eq(argv[1], "-?"))) { msg_error( "Syntax: erase # Fill section with 0xff values\n" @@ -726,7 +729,7 @@ static int cmd_erase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { if (argc > 1) { char *memtype = argv[1]; - AVRMEM *mem = avr_locate_mem(p, memtype); + const AVRMEM *mem = avr_locate_mem(p, memtype); if (mem == NULL) { pmsg_error("(erase) %s memory type not defined for part %s\n", argv[1], p->desc); return -1; @@ -752,7 +755,7 @@ static int cmd_erase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { if(rc == LIBAVRDUDE_SOFTFAIL) { pmsg_info("(erase) emulating chip erase by writing 0xff to flash "); - AVRMEM *flm = avr_locate_mem(p, "flash"); + const AVRMEM *flm = avr_locate_mem(p, "flash"); if(!flm) { msg_error("but flash not defined for part %s?\n", p->desc); return -1; @@ -792,7 +795,7 @@ static int cmd_erase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } -static int cmd_pgerase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_pgerase(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { if(argc != 3 || (argc > 1 && str_eq(argv[1], "-?"))) { msg_error( "Syntax: pgerase \n" @@ -802,7 +805,7 @@ static int cmd_pgerase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } char *memtype = argv[1]; - AVRMEM *mem = avr_locate_mem(p, memtype); + const AVRMEM *mem = avr_locate_mem(p, memtype); if(!mem) { pmsg_error("(pgerase) %s memory type not defined for part %s\n", memtype, p->desc); return -1; @@ -837,7 +840,7 @@ static int cmd_pgerase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { // Config command -const int MAX_PAD = 10; // Align value labels if difference between their lengths is less than this +static const int MAX_PAD = 10; // Align value labels if difference between their lengths is less than this typedef union { // Lock memory can be 1 or 4 bytes uint8_t b[4]; @@ -889,7 +892,7 @@ static int getfusel(const PROGRAMMER *pgm, const AVRPART *p, Fusel_t *fl, const goto back; } - AVRMEM *mem = avr_locate_mem(p, cci->memstr); + const AVRMEM *mem = avr_locate_mem(p, cci->memstr); if(!mem) { err = cache_string(tofree = str_sprintf("%s memory type not defined for part %s", cci->memstr, p->desc)); free(tofree); @@ -1138,7 +1141,7 @@ static void printfuse(Cfg_t *cc, int ii, Flock_t *fc, int nf, int printed, Cfg_o term_out("#\n"); } -static int cmd_config(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_config(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { Cfg_opts_t o = { 0 }; int help = 0, invalid = 0, itemac=1; @@ -1251,7 +1254,7 @@ static int cmd_config(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { cc[i].t = ct+i; const char *mt = str_starts(ct[i].memtype, "lock")? locktype: ct[i].memtype; cc[i].memstr = mt; - AVRMEM *mem = avr_locate_mem(p, mt); + const AVRMEM *mem = avr_locate_mem(p, mt); if(!mem) { pmsg_warning("(config) %s unavailable as memory %s is not defined for %s\n", ct[i].name, mt, p->desc); continue; @@ -1413,7 +1416,7 @@ static int cmd_config(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { fl_t towrite; towrite.i = (fusel.current & ~ct[ci].mask) | (toassign<desc); ret = -1; @@ -1443,7 +1446,7 @@ finished: } -static int cmd_part(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_part(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { if(argc > 1) { msg_error( "Syntax: part\n" @@ -1460,10 +1463,10 @@ static int cmd_part(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } -static int cmd_sig(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_sig(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { int i; int rc; - AVRMEM *m; + const AVRMEM *m; if(argc > 1) { msg_error( @@ -1493,7 +1496,7 @@ static int cmd_sig(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } -static int cmd_quit(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_quit(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { if(argc > 1) { msg_error( "Syntax: quit\n" @@ -1510,7 +1513,7 @@ static int cmd_quit(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } -static int cmd_parms(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_parms(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { if(argc > 1) { msg_error( "Syntax: parms\n" @@ -1525,7 +1528,7 @@ static int cmd_parms(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } -static int cmd_vtarg(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_vtarg(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { int rc; double v; char *endp; @@ -1550,7 +1553,7 @@ static int cmd_vtarg(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } -static int cmd_fosc(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_fosc(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { int rc; double v; char *endp; @@ -1583,7 +1586,7 @@ static int cmd_fosc(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } -static int cmd_sck(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_sck(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { int rc; double v; char *endp; @@ -1609,7 +1612,7 @@ static int cmd_sck(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } -static int cmd_varef(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_varef(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { int rc; unsigned int chan; double v; @@ -1651,7 +1654,7 @@ static int cmd_varef(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } -static int cmd_help(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_help(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { if(argc > 1) { msg_error( "Syntax: help\n" @@ -1677,7 +1680,7 @@ static int cmd_help(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { return 0; } -static int cmd_spi(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_spi(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { if(argc > 1) { msg_error( "Syntax: spi\n" @@ -1691,7 +1694,7 @@ static int cmd_spi(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { return 0; } -static int cmd_pgm(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_pgm(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { if(argc > 1) { msg_error( "Syntax: pgm\n" @@ -1707,7 +1710,7 @@ static int cmd_pgm(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } -static int cmd_verbose(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_verbose(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { int nverb; const char *errptr; @@ -1739,7 +1742,7 @@ static int cmd_verbose(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } -static int cmd_quell(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_quell(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { int nquell; const char *errptr; @@ -1834,7 +1837,7 @@ static char *tokenize(char *s, int *argcp, char ***argvp) { } -static int do_cmd(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int do_cmd(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { int i; int hold, matches; size_t len; @@ -1877,7 +1880,7 @@ char *terminal_get_input(const char *prompt) { } -static int process_line(char *q, PROGRAMMER *pgm, struct avrpart *p) { +static int process_line(char *q, const PROGRAMMER *pgm, const AVRPART *p) { int argc, rc = 0; char **argv; @@ -1906,11 +1909,27 @@ static int process_line(char *q, PROGRAMMER *pgm, struct avrpart *p) { } +/* + * Process individual terminal line + * - Used by main's -T argument + * - The terminal manages a cache, -U does not: the caller is responsible for executing + * + pgm->flush_cache(pgm, p) between -T line and -U memory read/avrdude exit + * + pgm->reset_cache(pgm, p) between -U memory write and -T line + */ + +int terminal_line(const PROGRAMMER *pgm, const AVRPART *p, const char *line) { + char *ln = cfg_strdup(__func__, line); + int ret = process_line(ln, pgm, p); + free(ln); + + return ret; +} + #if defined(HAVE_LIBREADLINE) -static PROGRAMMER *term_pgm; -static struct avrpart *term_p; +static const PROGRAMMER *term_pgm; +static const AVRPART *term_p; static int term_running; @@ -1960,7 +1979,7 @@ static int readytoread() { } // Callback processes commands whenever readline() has finished -void term_gotline(char *cmdstr) { +static void term_gotline(char *cmdstr) { if(cmdstr) { if(*cmdstr) { add_history(cmdstr); @@ -1991,7 +2010,7 @@ void term_gotline(char *cmdstr) { } -int terminal_mode_interactive(PROGRAMMER *pgm, struct avrpart *p) { +static int terminal_mode_interactive(const PROGRAMMER *pgm, const AVRPART *p) { term_pgm = pgm; // For callback routine term_p = p; @@ -2014,7 +2033,7 @@ int terminal_mode_interactive(PROGRAMMER *pgm, struct avrpart *p) { #endif -int terminal_mode_noninteractive(PROGRAMMER *pgm, struct avrpart *p) { +int terminal_mode_noninteractive(const PROGRAMMER *pgm, const AVRPART *p) { char *cmdbuf; int rc = 0; @@ -2030,7 +2049,9 @@ int terminal_mode_noninteractive(PROGRAMMER *pgm, struct avrpart *p) { return pgm->flush_cache(pgm, p); } -int terminal_mode(PROGRAMMER *pgm, struct avrpart *p) { + +// Terminal shell that is called on avrdude -t +int terminal_mode(const PROGRAMMER *pgm, const AVRPART *p) { #if defined(HAVE_LIBREADLINE) // GNU libreadline can also work if input is a pipe. // EditLine (NetBSD, MacOS) has issues with that, so only use it when diff --git a/src/term.h b/src/term.h deleted file mode 100644 index 61c4916c..00000000 --- a/src/term.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * avrdude - A Downloader/Uploader for AVR device programmers - * Copyright (C) 2000-2004 Brian S. Dean - * - * 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, see . - */ - -/* $Id$ */ - -#ifndef term_h -#define term_h - -#include "libavrdude.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - WRITE_MODE_STANDARD = 0, - WRITE_MODE_FILL = 1, -} mode; - -int terminal_mode(PROGRAMMER * pgm, struct avrpart * p); -char * terminal_get_input(const char *prompt); -void terminal_setup_update_progress(); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/update.c b/src/update.c index f6c71fcc..2ca33b33 100644 --- a/src/update.c +++ b/src/update.c @@ -42,15 +42,15 @@ * flash write). This allows colons in filenames other than those for * enclosing and separating , eg, C:/some/file.hex */ -UPDATE *parse_op(char *s) { +UPDATE *parse_op(const char *s) { // Assume -U [:] first UPDATE *upd = (UPDATE *) cfg_malloc(__func__, sizeof *upd); upd->memtype = NULL; // Defaults to flash or application upd->op = DEVICE_WRITE; - char *fn = s; + const char *fn = s; // Check for :c: start in which case override defaults - char *fc = strchr(s, ':'); + const char *fc = strchr(s, ':'); if(fc && fc[1] && fc[2] == ':') { if(!strchr("rwv", fc[1])) { pmsg_error("invalid I/O mode :%c: in -U %s\n", fc[1], s); @@ -95,8 +95,7 @@ UPDATE *parse_op(char *s) { } -UPDATE * dup_update(UPDATE * upd) -{ +UPDATE *dup_update(const UPDATE *upd) { UPDATE * u; u = (UPDATE *) cfg_malloc("dup_update()", sizeof(UPDATE)); @@ -112,20 +111,25 @@ UPDATE * dup_update(UPDATE * upd) return u; } -UPDATE * new_update(int op, char * memtype, int filefmt, char * filename) -{ +UPDATE *new_update(int op, const char *memstr, int filefmt, const char *fname) { UPDATE * u; u = (UPDATE *) cfg_malloc("new_update()", sizeof(UPDATE)); - u->memtype = cfg_strdup("new_update()", memtype); - u->filename = cfg_strdup("new_update()", filename); + u->memtype = cfg_strdup("new_update()", memstr); + u->filename = cfg_strdup("new_update()", fname); u->op = op; u->format = filefmt; return u; } +UPDATE *cmd_update(const char *cmd) { + UPDATE *u = (UPDATE *) cfg_malloc(__func__, sizeof *u); + u->cmdline = cmd; + return u; +} + void free_update(UPDATE * u) { if (u != NULL) { @@ -141,6 +145,15 @@ void free_update(UPDATE * u) } } +char *update_str(const UPDATE *upd) { + if(upd->cmdline) + return str_sprintf("-T %s", upd->cmdline); + return str_sprintf("-U %s:%c:%s:%c", + upd->memtype, + upd->op == DEVICE_READ? 'r': upd->op == DEVICE_WRITE? 'w': 'v', + upd->filename, + fileio_fmtchr(upd->format)); +} // Memory statistics considering holes after a file read returned size bytes int memstats(const AVRPART *p, const char *memtype, int size, Filestats *fsp) { @@ -211,39 +224,6 @@ int memstats(const AVRPART *p, const char *memtype, int size, Filestats *fsp) { } -// Convenience functions for printing -const char *update_plural(int x) { - return x==1? "": "s"; -} - -const char *update_inname(const char *fn) { - return !fn? "???": strcmp(fn, "-")? fn: ""; -} - -const char *update_outname(const char *fn) { - return !fn? "???": strcmp(fn, "-")? fn: ""; -} - -// Return sth like "[0, 0x1ff]" -const char *update_interval(int a, int b) { - // Cyclic buffer for 20+ temporary interval strings each max 41 bytes at 64-bit int - static char space[20*41 + 80], *sp; - if(!sp || sp-space > (int) sizeof space - 80) - sp = space; - - char *ret = sp; - - sprintf(sp, a<16? "[%d": "[0x%x", a); - sp += strlen(sp); - sprintf(sp, b<16? ", %d]": ", 0x%x]", b); - - // Advance beyond return string in temporary ring buffer - sp += strlen(sp)+1; - - return ret; -} - - // Helper functions for dry run to determine file access int update_is_okfile(const char *fn) { @@ -290,7 +270,7 @@ int update_is_readable(const char *fn) { static void ioerror(const char *iotype, const UPDATE *upd) { int errnocp = errno; - pmsg_ext_error("file %s is not %s: ", update_outname(upd->filename), iotype); + pmsg_ext_error("file %s is not %s: ", str_outname(upd->filename), iotype); if(errnocp) msg_ext_error("%s", strerror(errnocp)); else if(upd->filename && *upd->filename) @@ -298,13 +278,16 @@ static void ioerror(const char *iotype, const UPDATE *upd) { msg_ext_error("\n"); } -// Basic checks to reveal serious failure before programming +// Basic checks to reveal serious failure before programming (and on autodetect set format) int update_dryrun(const AVRPART *p, UPDATE *upd) { static char **wrote; static int nfwritten; int known, format_detect, ret = LIBAVRDUDE_SUCCESS; + if(upd->cmdline) // Todo: parse terminal command line? + return 0; + /* * Reject an update if memory name is not known amongst any part (suspect a typo) * but accept when the specific part does not have it (allow unifying i/faces) @@ -380,12 +363,20 @@ int update_dryrun(const AVRPART *p, UPDATE *upd) { } -int do_op(const PROGRAMMER *pgm, const AVRPART *p, UPDATE *upd, enum updateflags flags) { +int do_op(const PROGRAMMER *pgm, const AVRPART *p, const UPDATE *upd, enum updateflags flags) { AVRPART *v; AVRMEM *mem; int size; int rc; Filestats fs, fs_patched; + char *tofree; + + msg_info("\v\n"); + pmsg_info("processing %s\n", tofree = update_str(upd)); + free(tofree); + + if(upd->cmdline) + return terminal_line(pgm, p, upd->cmdline); mem = avr_locate_mem(p, upd->memtype); if (mem == NULL) { @@ -422,11 +413,11 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, UPDATE *upd, enum updateflags if (rc == 0) pmsg_notice("flash is empty, resulting file has no contents\n"); - pmsg_info("writing output file %s\n", update_outname(upd->filename)); + pmsg_info("writing output file %s\n", str_outname(upd->filename)); rc = fileio(FIO_WRITE, upd->filename, upd->format, p, upd->memtype, size); if (rc < 0) { - pmsg_error("write to file %s failed\n", update_outname(upd->filename)); + pmsg_error("write to file %s failed\n", str_outname(upd->filename)); return LIBAVRDUDE_GENERAL_FAILURE; } break; @@ -436,27 +427,27 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, UPDATE *upd, enum updateflags rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1); if (rc < 0) { - pmsg_error("read from file %s failed\n", update_inname(upd->filename)); + pmsg_error("read from file %s failed\n", str_inname(upd->filename)); return LIBAVRDUDE_GENERAL_FAILURE; } pmsg_info("reading input file %s for %s%s\n", - update_inname(upd->filename), mem->desc, alias_mem_desc); + str_inname(upd->filename), mem->desc, alias_mem_desc); if(memstats(p, upd->memtype, rc, &fs) < 0) return LIBAVRDUDE_GENERAL_FAILURE; imsg_info("with %d byte%s in %d section%s within %s\n", - fs.nbytes, update_plural(fs.nbytes), - fs.nsections, update_plural(fs.nsections), - update_interval(fs.firstaddr, fs.lastaddr)); + fs.nbytes, str_plural(fs.nbytes), + fs.nsections, str_plural(fs.nsections), + str_interval(fs.firstaddr, fs.lastaddr)); if(mem->page_size > 1) { imsg_info("using %d page%s and %d pad byte%s", - fs.npages, update_plural(fs.npages), - fs.nfill, update_plural(fs.nfill)); + fs.npages, str_plural(fs.npages), + fs.nfill, str_plural(fs.nfill)); if(fs.ntrailing) msg_info(", cutting off %d trailing 0xff byte%s", - fs.ntrailing, update_plural(fs.ntrailing)); + fs.ntrailing, str_plural(fs.ntrailing)); msg_info("\n"); } @@ -466,7 +457,7 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, UPDATE *upd, enum updateflags if(mem && !strcmp(mem->desc, "flash")) { rc = pgm->flash_readhook(pgm, p, mem, upd->filename, rc); if (rc < 0) { - pmsg_notice("readhook for file %s failed\n", update_inname(upd->filename)); + pmsg_notice("readhook for file %s failed\n", str_inname(upd->filename)); return LIBAVRDUDE_GENERAL_FAILURE; } if(memstats(p, upd->memtype, rc, &fs_patched) < 0) @@ -475,16 +466,16 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, UPDATE *upd, enum updateflags pmsg_info("preparing flash input for device%s\n", pgm->prog_modes & PM_SPM? " bootloader": ""); imsg_notice2("with %d byte%s in %d section%s within %s\n", - fs_patched.nbytes, update_plural(fs_patched.nbytes), - fs_patched.nsections, update_plural(fs_patched.nsections), - update_interval(fs_patched.firstaddr, fs_patched.lastaddr)); + fs_patched.nbytes, str_plural(fs_patched.nbytes), + fs_patched.nsections, str_plural(fs_patched.nsections), + str_interval(fs_patched.firstaddr, fs_patched.lastaddr)); if(mem->page_size > 1) { imsg_notice2("using %d page%s and %d pad byte%s", - fs_patched.npages, update_plural(fs_patched.npages), - fs_patched.nfill, update_plural(fs_patched.nfill)); + fs_patched.npages, str_plural(fs_patched.npages), + fs_patched.nfill, str_plural(fs_patched.nfill)); if(fs_patched.ntrailing) msg_notice2(", and %d trailing 0xff byte%s", - fs_patched.ntrailing, update_plural(fs_patched.ntrailing)); + fs_patched.ntrailing, str_plural(fs_patched.ntrailing)); msg_notice2("\n"); } } @@ -494,7 +485,7 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, UPDATE *upd, enum updateflags // Write the buffer contents to the selected memory type pmsg_info("writing %d byte%s %s%s ...\n", fs.nbytes, - update_plural(fs.nbytes), mem->desc, alias_mem_desc); + str_plural(fs.nbytes), mem->desc, alias_mem_desc); if (!(flags & UF_NOWRITE)) { if(mem->size > 32 || verbose > 1) @@ -512,7 +503,7 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, UPDATE *upd, enum updateflags } pmsg_info("%d byte%s of %s%s written\n", fs.nbytes, - update_plural(fs.nbytes), mem->desc, alias_mem_desc); + str_plural(fs.nbytes), mem->desc, alias_mem_desc); if (!(flags & UF_VERIFY)) // Fall through for auto verify unless break; @@ -525,17 +516,17 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, UPDATE *upd, enum updateflags int userverify = upd->op == DEVICE_VERIFY; // Explicit -U :v by user pmsg_info("verifying %s%s memory against %s\n", mem->desc, - alias_mem_desc, update_inname(upd->filename)); + alias_mem_desc, str_inname(upd->filename)); // No need to read file when fallen through from DEVICE_WRITE if (userverify) { pmsg_notice("load %s%s data from input file %s\n", mem->desc, - alias_mem_desc, update_inname(upd->filename)); + alias_mem_desc, str_inname(upd->filename)); rc = fileio(FIO_READ_FOR_VERIFY, upd->filename, upd->format, p, upd->memtype, -1); if (rc < 0) { - pmsg_error("read from file %s failed\n", update_inname(upd->filename)); + pmsg_error("read from file %s failed\n", str_inname(upd->filename)); return LIBAVRDUDE_GENERAL_FAILURE; } size = rc; @@ -552,7 +543,7 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, UPDATE *upd, enum updateflags if (quell_progress < 2) { if (userverify) pmsg_notice("input file %s contains %d byte%s\n", - update_inname(upd->filename), fs.nbytes, update_plural(fs.nbytes)); + str_inname(upd->filename), fs.nbytes, str_plural(fs.nbytes)); pmsg_notice2("reading on-chip %s%s data ...\n", mem->desc, alias_mem_desc); } @@ -579,7 +570,7 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, UPDATE *upd, enum updateflags } int verified = fs.nbytes+fs.ntrailing; - pmsg_info("%d byte%s of %s%s verified\n", verified, update_plural(verified), mem->desc, alias_mem_desc); + pmsg_info("%d byte%s of %s%s verified\n", verified, str_plural(verified), mem->desc, alias_mem_desc); pgm->vfy_led(pgm, OFF); avr_free_part(v);