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.)


git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk@654 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
Joerg Wunsch 2006-09-08 21:28:24 +00:00
parent ac7bf0624c
commit 16c7a11538
6 changed files with 179 additions and 1 deletions

View File

@ -1,3 +1,16 @@
2006-09-08 Joerg Wunsch <j@uriah.heep.sax.de>
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 <j@uriah.heep.sax.de> 2006-09-08 Joerg Wunsch <j@uriah.heep.sax.de>
* fileio.c: CPP statements start in column #1. * fileio.c: CPP statements start in column #1.

View File

@ -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 auto detect; valid for input only, and only if the input is not
provided at provided at
.Em stdin . .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 .El
.Pp .Pp
The default is to use auto detection for input files, and raw binary The default is to use auto detection for input files, and raw binary

View File

@ -749,6 +749,23 @@ treated as decimal.
auto detect; valid for input only, and only if the input is not provided auto detect; valid for input only, and only if the input is not provided
at stdin. 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 @end table
The default is to use auto detection for input files, and raw binary The default is to use auto detection for input files, and raw binary

View File

@ -77,6 +77,10 @@ int fileio_ihex(struct fioparms * fio,
int fileio_srec(struct fioparms * fio, int fileio_srec(struct fioparms * fio,
char * filename, FILE * f, unsigned char * buf, int size); 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); int fmt_autodetect(char * fname);
@ -658,6 +662,45 @@ int srec2b(char * infile, FILE * inf,
return maxaddr; 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, int fileio_rbin(struct fioparms * fio,
char * filename, FILE * f, unsigned char * buf, int size) 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) int fileio_setparms(int op, struct fioparms * fp)
{ {
fp->op = op; fp->op = op;
@ -1005,6 +1120,13 @@ int fileio(int op, char * filename, FILEFMT format,
rc = fileio_imm(&fio, fname, f, buf, size); rc = fileio_imm(&fio, fname, f, buf, size);
break; break;
case FMT_HEX:
case FMT_DEC:
case FMT_OCT:
case FMT_BIN:
rc = fileio_num(&fio, fname, f, buf, size, format);
break;
default: default:
fprintf(stderr, "%s: invalid %s file format: %d\n", fprintf(stderr, "%s: invalid %s file format: %d\n",
progname, fio.iodesc, format); progname, fio.iodesc, format);

View File

@ -27,7 +27,11 @@ typedef enum {
FMT_SREC, FMT_SREC,
FMT_IHEX, FMT_IHEX,
FMT_RBIN, FMT_RBIN,
FMT_IMM FMT_IMM,
FMT_HEX,
FMT_DEC,
FMT_OCT,
FMT_BIN
} FILEFMT; } FILEFMT;
struct fioparms { struct fioparms {

View File

@ -414,6 +414,10 @@ UPDATE * parse_op(char * s)
case 'i': upd->format = FMT_IHEX; break; case 'i': upd->format = FMT_IHEX; break;
case 'r': upd->format = FMT_RBIN; break; case 'r': upd->format = FMT_RBIN; break;
case 'm': upd->format = FMT_IMM; 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: default:
fprintf(stderr, "%s: invalid file format '%s' in update specifier\n", fprintf(stderr, "%s: invalid file format '%s' in update specifier\n",
progname, p); progname, p);