diff --git a/ChangeLog b/ChangeLog index da8d8cbf..d1115fd0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2006-09-08 Joerg Wunsch + + Implement numerical output formats for decimal, hexadecimal, + octal, and binary numbers. + Closes bug #16129: more output formats for fuse bits + (avrdude enhancement request) + * fileio.c: Implement fileio_num() and the itoa_simple() + helper function. + * fileio.h: Add new file formats to FILEFMT. + * main.c: Parse the new file formats. + * avrdude.1: Document all this. + * doc/avrdude.texi: (Ditto.) + 2006-09-08 Joerg Wunsch * fileio.c: CPP statements start in column #1. diff --git a/avrdude.1 b/avrdude.1 index 26fb9493..c652be0a 100644 --- a/avrdude.1 +++ b/avrdude.1 @@ -505,6 +505,24 @@ having to create a single-byte file or enter terminal mode. auto detect; valid for input only, and only if the input is not provided at .Em stdin . +.It Ar d +decimal; this and the following formats are only valid on output. +They generate one line of output for the respective memory section, +forming a comma-separated list of the values. +This can be particularly useful for subsequent processing, like for +fuse bit settings. +.It Ar h +hexadecimal; each value will get the string +.Em 0x +prepended. +.It Ar o +octal; each value will get a +.Em 0 +prepended unless it is less than 8 in which case it gets no prefix. +.It Ar b +binary; each value will get the string +.Em 0b +prepended. .El .Pp The default is to use auto detection for input files, and raw binary diff --git a/doc/avrdude.texi b/doc/avrdude.texi index 192c5ce3..78939a5c 100644 --- a/doc/avrdude.texi +++ b/doc/avrdude.texi @@ -749,6 +749,23 @@ treated as decimal. auto detect; valid for input only, and only if the input is not provided at stdin. +@itemx d +decimal; this and the following formats are only valid on output. +They generate one line of output for the respective memory section, +forming a comma-separated list of the values. +This can be particularly useful for subsequent processing, like for +fuse bit settings. + +@itemx h +hexadecimal; each value will get the string @emph{0x} prepended. + +@itemx o +octal; each value will get a @emph{0} +prepended unless it is less than 8 in which case it gets no prefix. + +@itemx b +binary; each value will get the string @emph{0b} prepended. + @end table The default is to use auto detection for input files, and raw binary diff --git a/fileio.c b/fileio.c index 0e3b18e1..2f14b6d3 100644 --- a/fileio.c +++ b/fileio.c @@ -77,6 +77,10 @@ int fileio_ihex(struct fioparms * fio, int fileio_srec(struct fioparms * fio, char * filename, FILE * f, unsigned char * buf, int size); +int fileio_num(struct fioparms * fio, + char * filename, FILE * f, unsigned char * buf, int size, + FILEFMT fmt); + int fmt_autodetect(char * fname); @@ -658,6 +662,45 @@ int srec2b(char * infile, FILE * inf, return maxaddr; } +/* + * Simple itoa() implementation. Caller needs to allocate enough + * space in buf. Only positive integers are handled. + */ +static char *itoa_simple(int n, char *buf, int base) +{ + div_t q; + char c, *cp, *cp2; + + cp = buf; + /* + * Divide by base until the number disappeared, but ensure at least + * one digit will be emitted. + */ + do { + q = div(n, base); + n = q.quot; + if (q.rem >= 10) + c = q.rem - 10 + 'a'; + else + c = q.rem + '0'; + *cp++ = c; + } while (q.quot != 0); + + /* Terminate the string. */ + *cp-- = '\0'; + + /* Now revert the result string. */ + cp2 = buf; + while (cp > cp2) { + c = *cp; + *cp-- = *cp2; + *cp2++ = c; + } + + return buf; +} + + int fileio_rbin(struct fioparms * fio, char * filename, FILE * f, unsigned char * buf, int size) @@ -793,6 +836,78 @@ int fileio_srec(struct fioparms * fio, } +int fileio_num(struct fioparms * fio, + char * filename, FILE * f, unsigned char * buf, int size, + FILEFMT fmt) +{ + const char *prefix; + char cbuf[20]; + int base, i, num; + + switch (fmt) { + case FMT_HEX: + prefix = "0x"; + base = 16; + break; + + default: + case FMT_DEC: + prefix = ""; + base = 10; + break; + + case FMT_OCT: + prefix = "0"; + base = 8; + break; + + case FMT_BIN: + prefix = "0b"; + base = 2; + break; + + } + + switch (fio->op) { + case FIO_WRITE: + break; + default: + fprintf(stderr, "%s: fileio: invalid operation=%d\n", + progname, fio->op); + return -1; + } + + for (i = 0; i < size; i++) { + if (i > 0) { + if (putc(',', f) == EOF) + goto writeerr; + } + num = (unsigned int)buf[i]; + /* + * For a base of 8 and a value < 8 to convert, don't write the + * prefix. The conversion will be indistinguishable from a + * decimal one then. + */ + if (prefix[0] != '\0' && !(base == 8 && num < 8)) { + if (fputs(prefix, f) == EOF) + goto writeerr; + } + itoa_simple(num, cbuf, base); + if (fputs(cbuf, f) == EOF) + goto writeerr; + } + if (putc('\n', f) == EOF) + goto writeerr; + + return 0; + + writeerr: + fprintf(stderr, "%s: error writing to %s: %s\n", + progname, filename, strerror(errno)); + return -1; +} + + int fileio_setparms(int op, struct fioparms * fp) { fp->op = op; @@ -1005,6 +1120,13 @@ int fileio(int op, char * filename, FILEFMT format, rc = fileio_imm(&fio, fname, f, buf, size); break; + case FMT_HEX: + case FMT_DEC: + case FMT_OCT: + case FMT_BIN: + rc = fileio_num(&fio, fname, f, buf, size, format); + break; + default: fprintf(stderr, "%s: invalid %s file format: %d\n", progname, fio.iodesc, format); diff --git a/fileio.h b/fileio.h index 63082c25..08efc492 100644 --- a/fileio.h +++ b/fileio.h @@ -27,7 +27,11 @@ typedef enum { FMT_SREC, FMT_IHEX, FMT_RBIN, - FMT_IMM + FMT_IMM, + FMT_HEX, + FMT_DEC, + FMT_OCT, + FMT_BIN } FILEFMT; struct fioparms { diff --git a/main.c b/main.c index 15f16aaf..5e00e645 100644 --- a/main.c +++ b/main.c @@ -414,6 +414,10 @@ UPDATE * parse_op(char * s) case 'i': upd->format = FMT_IHEX; break; case 'r': upd->format = FMT_RBIN; break; case 'm': upd->format = FMT_IMM; break; + case 'b': upd->format = FMT_BIN; break; + case 'd': upd->format = FMT_DEC; break; + case 'h': upd->format = FMT_HEX; break; + case 'o': upd->format = FMT_OCT; break; default: fprintf(stderr, "%s: invalid file format '%s' in update specifier\n", progname, p);