Replace string arrays with const char * and allocated space (part 2)
This commit replaces fixed-string buffers in PROGRAMMER, AVRPART and AVRMEM that are dealt with by the parser and grammar. Now, string assignments are always to const char *, ie, these are read-only strings with arbitrary length. config_gram.y now only needs to consider one type of string assignment. This commit also - Replaces the simple linear-search cache_string() function with faster hashed cache_string(). Either way, the returned value is likely to be shared, so should never be free()'d. - Duplicates hvupdi_support list in pgm_dup() and frees it in pgm_free() - Adds const qualifier to some function args in avrpart.c and pgm.c - Hardens some functions against being called with NULL pointers - Ensures _new() and _dup() functions for parts, programmers and memory return a suitable memory. Out of memory triggers exit in one of three functions, cfg_malloc(), cfg_realloc() and cfg_strdup(); there is rarely anything useful that AVRDUDE or, for that matter, any application compiled against libavrdude can do once you run out of memory as AVRDUDE/libavrdude rely heavily on allocation of memory.
This commit is contained in:
parent
7375477f70
commit
f4c5a8350d
408
src/avrpart.c
408
src/avrpart.c
|
@ -1,4 +1,3 @@
|
|||
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
|
@ -31,44 +30,23 @@
|
|||
*** Elementary functions dealing with OPCODE structures
|
||||
***/
|
||||
|
||||
OPCODE * avr_new_opcode(void)
|
||||
{
|
||||
OPCODE * m;
|
||||
|
||||
m = (OPCODE *)malloc(sizeof(*m));
|
||||
if (m == NULL) {
|
||||
avrdude_message(MSG_INFO, "avr_new_opcode(): out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(m, 0, sizeof(*m));
|
||||
|
||||
return m;
|
||||
OPCODE *avr_new_opcode(void) {
|
||||
return (OPCODE *) cfg_malloc("avr_new_opcode()", sizeof(OPCODE));
|
||||
}
|
||||
|
||||
static OPCODE * avr_dup_opcode(OPCODE * op)
|
||||
{
|
||||
OPCODE * m;
|
||||
|
||||
/* this makes life easier */
|
||||
if (op == NULL) {
|
||||
static OPCODE *avr_dup_opcode(const OPCODE *op) {
|
||||
if(op == NULL) // Caller wants NULL if op == NULL
|
||||
return NULL;
|
||||
}
|
||||
|
||||
m = (OPCODE *)malloc(sizeof(*m));
|
||||
if (m == NULL) {
|
||||
avrdude_message(MSG_INFO, "avr_dup_opcode(): out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
OPCODE *m = (OPCODE *) cfg_malloc("avr_dup_opcode()", sizeof(*m));
|
||||
memcpy(m, op, sizeof(*m));
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
void avr_free_opcode(OPCODE * op)
|
||||
{
|
||||
free(op);
|
||||
void avr_free_opcode(OPCODE *op) {
|
||||
if(op)
|
||||
free(op);
|
||||
}
|
||||
|
||||
|
||||
|
@ -268,11 +246,10 @@ int avr_set_input(OPCODE * op, unsigned char * cmd, unsigned char data)
|
|||
/*
|
||||
* avr_get_output()
|
||||
*
|
||||
* Retreive output data bits from the command results based on the
|
||||
* Retrieve output data bits from the command results based on the
|
||||
* opcode data.
|
||||
*/
|
||||
int avr_get_output(OPCODE * op, unsigned char * res, unsigned char * data)
|
||||
{
|
||||
int avr_get_output(const OPCODE *op, const unsigned char *res, unsigned char *data) {
|
||||
int i, j, bit;
|
||||
unsigned char value;
|
||||
unsigned char mask;
|
||||
|
@ -301,8 +278,7 @@ int avr_get_output(OPCODE * op, unsigned char * res, unsigned char * data)
|
|||
* Calculate the byte number of the output data based on the
|
||||
* opcode data.
|
||||
*/
|
||||
int avr_get_output_index(OPCODE * op)
|
||||
{
|
||||
int avr_get_output_index(const OPCODE *op) {
|
||||
int i, j;
|
||||
|
||||
for (i=0; i<32; i++) {
|
||||
|
@ -353,34 +329,17 @@ static char * bittype(int type)
|
|||
*** Elementary functions dealing with AVRMEM structures
|
||||
***/
|
||||
|
||||
AVRMEM * avr_new_memtype(void)
|
||||
{
|
||||
AVRMEM * m;
|
||||
|
||||
m = (AVRMEM *)malloc(sizeof(*m));
|
||||
if (m == NULL) {
|
||||
avrdude_message(MSG_INFO, "avr_new_memtype(): out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(m, 0, sizeof(*m));
|
||||
AVRMEM *avr_new_memtype(void) {
|
||||
AVRMEM *m = (AVRMEM *) cfg_malloc("avr_new_memtype()", sizeof(*m));
|
||||
m->desc = cache_string("");
|
||||
m->page_size = 1; // ensure not 0
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
AVRMEM_ALIAS * avr_new_memalias(void)
|
||||
{
|
||||
AVRMEM_ALIAS * m;
|
||||
|
||||
m = (AVRMEM_ALIAS *)malloc(sizeof(*m));
|
||||
if (m == NULL) {
|
||||
avrdude_message(MSG_INFO, "avr_new_memalias(): out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(m, 0, sizeof(*m));
|
||||
|
||||
AVRMEM_ALIAS *avr_new_memalias(void) {
|
||||
AVRMEM_ALIAS *m = (AVRMEM_ALIAS *) cfg_malloc("avr_new_memalias()", sizeof*m);
|
||||
m->desc = cache_string("");
|
||||
return m;
|
||||
}
|
||||
|
||||
|
@ -389,106 +348,79 @@ AVRMEM_ALIAS * avr_new_memalias(void)
|
|||
* Allocate and initialize memory buffers for each of the device's
|
||||
* defined memory regions.
|
||||
*/
|
||||
int avr_initmem(AVRPART * p)
|
||||
{
|
||||
LNODEID ln;
|
||||
AVRMEM * m;
|
||||
int avr_initmem(const AVRPART *p) {
|
||||
if(p == NULL || p->mem == NULL)
|
||||
return -1;
|
||||
|
||||
for (ln=lfirst(p->mem); ln; ln=lnext(ln)) {
|
||||
m = ldata(ln);
|
||||
m->buf = (unsigned char *) malloc(m->size);
|
||||
if (m->buf == NULL) {
|
||||
avrdude_message(MSG_INFO, "%s: can't alloc buffer for %s size of %d bytes\n",
|
||||
progname, m->desc, m->size);
|
||||
return -1;
|
||||
}
|
||||
m->tags = (unsigned char *) malloc(m->size);
|
||||
if (m->tags == NULL) {
|
||||
avrdude_message(MSG_INFO, "%s: can't alloc buffer for %s size of %d bytes\n",
|
||||
progname, m->desc, m->size);
|
||||
return -1;
|
||||
}
|
||||
for (LNODEID ln=lfirst(p->mem); ln; ln=lnext(ln)) {
|
||||
AVRMEM *m = ldata(ln);
|
||||
m->buf = (unsigned char *) cfg_malloc("avr_initmem()", m->size);
|
||||
m->tags = (unsigned char *) cfg_malloc("avr_initmem()", m->size);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
AVRMEM * avr_dup_mem(AVRMEM * m)
|
||||
{
|
||||
AVRMEM * n;
|
||||
int i;
|
||||
AVRMEM *avr_dup_mem(const AVRMEM *m) {
|
||||
AVRMEM *n = avr_new_memtype();
|
||||
|
||||
n = avr_new_memtype();
|
||||
if(m) {
|
||||
*n = *m;
|
||||
|
||||
*n = *m;
|
||||
|
||||
if (m->buf != NULL) {
|
||||
n->buf = (unsigned char *)malloc(n->size);
|
||||
if (n->buf == NULL) {
|
||||
avrdude_message(MSG_INFO, "avr_dup_mem(): out of memory (memsize=%d)\n",
|
||||
n->size);
|
||||
exit(1);
|
||||
if(m->buf) {
|
||||
n->buf = (unsigned char *) cfg_malloc("avr_dup_mem()", n->size);
|
||||
memcpy(n->buf, m->buf, n->size);
|
||||
}
|
||||
memcpy(n->buf, m->buf, n->size);
|
||||
}
|
||||
|
||||
if (m->tags != NULL) {
|
||||
n->tags = (unsigned char *)malloc(n->size);
|
||||
if (n->tags == NULL) {
|
||||
avrdude_message(MSG_INFO, "avr_dup_mem(): out of memory (memsize=%d)\n",
|
||||
n->size);
|
||||
exit(1);
|
||||
if(m->tags) {
|
||||
n->tags = (unsigned char *) cfg_malloc("avr_dup_mem()", n->size);
|
||||
memcpy(n->tags, m->tags, n->size);
|
||||
}
|
||||
memcpy(n->tags, m->tags, n->size);
|
||||
}
|
||||
|
||||
for (i = 0; i < AVR_OP_MAX; i++) {
|
||||
n->op[i] = avr_dup_opcode(n->op[i]);
|
||||
for(int i = 0; i < AVR_OP_MAX; i++)
|
||||
n->op[i] = avr_dup_opcode(n->op[i]);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
AVRMEM_ALIAS * avr_dup_memalias(AVRMEM_ALIAS * m)
|
||||
{
|
||||
AVRMEM_ALIAS * n;
|
||||
AVRMEM_ALIAS *avr_dup_memalias(const AVRMEM_ALIAS *m) {
|
||||
AVRMEM_ALIAS *n = avr_new_memalias();
|
||||
|
||||
n = avr_new_memalias();
|
||||
|
||||
*n = *m;
|
||||
if(m)
|
||||
*n = *m;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
void avr_free_mem(AVRMEM * m)
|
||||
{
|
||||
if (m->buf != NULL) {
|
||||
free(m->buf);
|
||||
m->buf = NULL;
|
||||
}
|
||||
if (m->tags != NULL) {
|
||||
free(m->tags);
|
||||
m->tags = NULL;
|
||||
}
|
||||
for(size_t i=0; i<sizeof(m->op)/sizeof(m->op[0]); i++)
|
||||
{
|
||||
if (m->op[i] != NULL)
|
||||
{
|
||||
avr_free_opcode(m->op[i]);
|
||||
m->op[i] = NULL;
|
||||
}
|
||||
}
|
||||
free(m);
|
||||
}
|
||||
void avr_free_mem(AVRMEM * m) {
|
||||
if(m == NULL)
|
||||
return;
|
||||
|
||||
void avr_free_memalias(AVRMEM_ALIAS * m)
|
||||
{
|
||||
if(m->buf) {
|
||||
free(m->buf);
|
||||
m->buf = NULL;
|
||||
}
|
||||
if(m->tags) {
|
||||
free(m->tags);
|
||||
m->tags = NULL;
|
||||
}
|
||||
for(size_t i=0; i<sizeof(m->op)/sizeof(m->op[0]); i++) {
|
||||
if(m->op[i]) {
|
||||
avr_free_opcode(m->op[i]);
|
||||
m->op[i] = NULL;
|
||||
}
|
||||
}
|
||||
free(m);
|
||||
}
|
||||
|
||||
AVRMEM_ALIAS * avr_locate_memalias(AVRPART * p, const char * desc)
|
||||
{
|
||||
void avr_free_memalias(AVRMEM_ALIAS *m) {
|
||||
if(m)
|
||||
free(m);
|
||||
}
|
||||
|
||||
AVRMEM_ALIAS *avr_locate_memalias(const AVRPART *p, const char *desc) {
|
||||
AVRMEM_ALIAS * m, * match;
|
||||
LNODEID ln;
|
||||
int matches;
|
||||
|
@ -514,8 +446,7 @@ AVRMEM_ALIAS * avr_locate_memalias(AVRPART * p, const char * desc)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
AVRMEM * avr_locate_mem_noalias(AVRPART * p, const char * desc)
|
||||
{
|
||||
AVRMEM *avr_locate_mem_noalias(const AVRPART *p, const char *desc) {
|
||||
AVRMEM * m, * match;
|
||||
LNODEID ln;
|
||||
int matches;
|
||||
|
@ -542,8 +473,7 @@ AVRMEM * avr_locate_mem_noalias(AVRPART * p, const char * desc)
|
|||
}
|
||||
|
||||
|
||||
AVRMEM * avr_locate_mem(AVRPART * p, const char * desc)
|
||||
{
|
||||
AVRMEM *avr_locate_mem(const AVRPART *p, const char *desc) {
|
||||
AVRMEM * m, * match;
|
||||
AVRMEM_ALIAS * alias;
|
||||
LNODEID ln;
|
||||
|
@ -577,24 +507,20 @@ AVRMEM * avr_locate_mem(AVRPART * p, const char * desc)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
AVRMEM_ALIAS * avr_find_memalias(AVRPART * p, AVRMEM * m_orig)
|
||||
{
|
||||
AVRMEM_ALIAS * m;
|
||||
LNODEID ln;
|
||||
|
||||
for (ln=lfirst(p->mem_alias); ln; ln=lnext(ln)) {
|
||||
m = ldata(ln);
|
||||
if (m->aliased_mem == m_orig)
|
||||
return m;
|
||||
}
|
||||
AVRMEM_ALIAS *avr_find_memalias(const AVRPART *p, const AVRMEM *m_orig) {
|
||||
if(p && p->mem_alias && m_orig)
|
||||
for(LNODEID ln=lfirst(p->mem_alias); ln; ln=lnext(ln)) {
|
||||
AVRMEM_ALIAS *m = ldata(ln);
|
||||
if(m->aliased_mem == m_orig)
|
||||
return m;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, AVRPART * p,
|
||||
int type, int verbose)
|
||||
{
|
||||
void avr_mem_display(const char *prefix, FILE *f, const AVRMEM *m,
|
||||
const AVRPART *p, int verbose) {
|
||||
static unsigned int prev_mem_offset;
|
||||
static int prev_mem_size;
|
||||
int i, j;
|
||||
|
@ -623,7 +549,7 @@ void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, AVRPART * p,
|
|||
AVRMEM_ALIAS *ap = avr_find_memalias(p, m);
|
||||
/* Show alias if the current and the next memory section has the same offset
|
||||
and size, we're not out of band and a family_id is present */
|
||||
char * mem_desc_alias = ap? ap->desc: "";
|
||||
const char *mem_desc_alias = ap? ap->desc: "";
|
||||
fprintf(f,
|
||||
"%s%-11s %-8s %4d %5d %5d %4d %-6s %6d %4d %6d %5d %5d 0x%02x 0x%02x\n",
|
||||
prefix,
|
||||
|
@ -669,74 +595,63 @@ void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, AVRPART * p,
|
|||
* Elementary functions dealing with AVRPART structures
|
||||
*/
|
||||
|
||||
AVRPART * avr_new_part(void)
|
||||
{
|
||||
AVRPART * p;
|
||||
AVRPART *avr_new_part(void) {
|
||||
AVRPART *p = (AVRPART *) cfg_malloc("avr_new_part()", sizeof(AVRPART));
|
||||
const char *nulp = cache_string("");
|
||||
|
||||
p = (AVRPART *)malloc(sizeof(AVRPART));
|
||||
if (p == NULL) {
|
||||
avrdude_message(MSG_INFO, "new_part(): out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(p, 0, sizeof(*p));
|
||||
|
||||
p->id[0] = 0;
|
||||
p->desc[0] = 0;
|
||||
// Initialise const char * and LISTID entities
|
||||
p->desc = nulp;
|
||||
p->id = nulp;
|
||||
p->parent_id = nulp;
|
||||
p->family_id = nulp;
|
||||
p->config_file = nulp;
|
||||
p->mem = lcreat(NULL, 0);
|
||||
p->mem_alias = lcreat(NULL, 0);
|
||||
|
||||
// Default values
|
||||
p->hvupdi_variant = -1;
|
||||
memset(p->signature, 0xFF, 3);
|
||||
p->reset_disposition = RESET_DEDICATED;
|
||||
p->retry_pulse = PIN_AVR_SCK;
|
||||
p->flags = AVRPART_SERIALOK | AVRPART_PARALLELOK | AVRPART_ENABLEPAGEPROGRAMMING;
|
||||
p->parent_id = nulp;
|
||||
p->config_file = nulp;
|
||||
p->lineno = 0;
|
||||
memset(p->signature, 0xFF, 3);
|
||||
p->ctl_stack_type = CTL_STACK_NONE;
|
||||
p->ocdrev = -1;
|
||||
p->hvupdi_variant = -1;
|
||||
|
||||
p->mem = lcreat(NULL, 0);
|
||||
p->mem_alias = lcreat(NULL, 0);
|
||||
p->lineno = 0;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
AVRPART * avr_dup_part(AVRPART * d)
|
||||
{
|
||||
AVRPART * p;
|
||||
LISTID save, save2;
|
||||
LNODEID ln, ln2;
|
||||
int i;
|
||||
AVRPART *avr_dup_part(const AVRPART *d) {
|
||||
AVRPART *p = avr_new_part();
|
||||
|
||||
p = avr_new_part();
|
||||
save = p->mem;
|
||||
save2 = p->mem_alias;
|
||||
if(d) {
|
||||
*p = *d;
|
||||
|
||||
*p = *d;
|
||||
// Duplicate the memory and alias chains
|
||||
p->mem = lcreat(NULL, 0);
|
||||
p->mem_alias = lcreat(NULL, 0);
|
||||
|
||||
p->mem = save;
|
||||
p->mem_alias = save2;
|
||||
for (ln=lfirst(d->mem); ln; ln=lnext(ln)) {
|
||||
AVRMEM *m = ldata(ln);
|
||||
AVRMEM *m2 = avr_dup_mem(m);
|
||||
ladd(p->mem, m2);
|
||||
// see if there is any alias for it
|
||||
for (ln2=lfirst(d->mem_alias); ln2; ln2=lnext(ln2)) {
|
||||
AVRMEM_ALIAS *a = ldata(ln2);
|
||||
if (a->aliased_mem == m) {
|
||||
// yes, duplicate it
|
||||
AVRMEM_ALIAS *a2 = avr_dup_memalias(a);
|
||||
// ... adjust the pointer ...
|
||||
a2->aliased_mem = m2;
|
||||
// ... and add to new list
|
||||
ladd(p->mem_alias, a2);
|
||||
for(LNODEID ln=lfirst(d->mem); ln; ln=lnext(ln)) {
|
||||
AVRMEM *m = ldata(ln);
|
||||
AVRMEM *m2 = avr_dup_mem(m);
|
||||
ladd(p->mem, m2);
|
||||
// See if there is any alias for it
|
||||
for(LNODEID ln2=lfirst(d->mem_alias); ln2; ln2=lnext(ln2)) {
|
||||
AVRMEM_ALIAS *a = ldata(ln2);
|
||||
if (a->aliased_mem == m) {
|
||||
// Yes, duplicate it, adjust the pointer and add to new list
|
||||
AVRMEM_ALIAS *a2 = avr_dup_memalias(a);
|
||||
a2->aliased_mem = m2;
|
||||
ladd(p->mem_alias, a2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < AVR_OP_MAX; i++) {
|
||||
p->op[i] = avr_dup_opcode(p->op[i]);
|
||||
for(int i = 0; i < AVR_OP_MAX; i++)
|
||||
p->op[i] = avr_dup_opcode(p->op[i]);
|
||||
}
|
||||
|
||||
return p;
|
||||
|
@ -758,61 +673,45 @@ void avr_free_part(AVRPART * d)
|
|||
free(d);
|
||||
}
|
||||
|
||||
AVRPART * locate_part(LISTID parts, const char * partdesc)
|
||||
{
|
||||
LNODEID ln1;
|
||||
AVRPART *locate_part(const LISTID parts, const char *partdesc) {
|
||||
AVRPART * p = NULL;
|
||||
int found;
|
||||
int found = 0;
|
||||
|
||||
if(!parts || !partdesc)
|
||||
return NULL;
|
||||
|
||||
found = 0;
|
||||
|
||||
for (ln1=lfirst(parts); ln1 && !found; ln1=lnext(ln1)) {
|
||||
for (LNODEID ln1=lfirst(parts); ln1 && !found; ln1=lnext(ln1)) {
|
||||
p = ldata(ln1);
|
||||
if ((strcasecmp(partdesc, p->id) == 0) ||
|
||||
(strcasecmp(partdesc, p->desc) == 0))
|
||||
found = 1;
|
||||
}
|
||||
|
||||
if (found)
|
||||
return p;
|
||||
|
||||
return NULL;
|
||||
return found? p: NULL;
|
||||
}
|
||||
|
||||
AVRPART * locate_part_by_avr910_devcode(LISTID parts, int devcode)
|
||||
{
|
||||
LNODEID ln1;
|
||||
AVRPART * p = NULL;
|
||||
|
||||
for (ln1=lfirst(parts); ln1; ln1=lnext(ln1)) {
|
||||
p = ldata(ln1);
|
||||
if (p->avr910_devcode == devcode)
|
||||
return p;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
AVRPART * locate_part_by_signature(LISTID parts, unsigned char * sig,
|
||||
int sigsize)
|
||||
{
|
||||
LNODEID ln1;
|
||||
AVRPART * p = NULL;
|
||||
int i;
|
||||
|
||||
if (sigsize == 3) {
|
||||
for (ln1=lfirst(parts); ln1; ln1=lnext(ln1)) {
|
||||
p = ldata(ln1);
|
||||
for (i=0; i<3; i++)
|
||||
if (p->signature[i] != sig[i])
|
||||
break;
|
||||
if (i == 3)
|
||||
AVRPART *locate_part_by_avr910_devcode(const LISTID parts, int devcode) {
|
||||
if(parts)
|
||||
for (LNODEID ln1=lfirst(parts); ln1; ln1=lnext(ln1)) {
|
||||
AVRPART * p = ldata(ln1);
|
||||
if (p->avr910_devcode == devcode)
|
||||
return p;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
AVRPART *locate_part_by_signature(const LISTID parts, unsigned char *sig, int sigsize) {
|
||||
if(parts && sigsize == 3)
|
||||
for(LNODEID ln1=lfirst(parts); ln1; ln1=lnext(ln1)) {
|
||||
AVRPART *p = ldata(ln1);
|
||||
int i;
|
||||
for(i=0; i<3; i++)
|
||||
if(p->signature[i] != sig[i])
|
||||
break;
|
||||
if(i == 3)
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -841,12 +740,11 @@ void walk_avrparts(LISTID avrparts, walk_avrparts_cb cb, void *cookie)
|
|||
/*
|
||||
* Compare function to sort the list of programmers
|
||||
*/
|
||||
static int sort_avrparts_compare(AVRPART * p1,AVRPART * p2)
|
||||
{
|
||||
if(p1 == NULL || p2 == NULL) {
|
||||
static int sort_avrparts_compare(const AVRPART *p1, const AVRPART *p2) {
|
||||
if(p1 == NULL || p1->desc == NULL || p2 == NULL || p2->desc == NULL)
|
||||
return 0;
|
||||
}
|
||||
return strncasecmp(p1->desc,p2->desc,AVR_DESCLEN);
|
||||
|
||||
return strcasecmp(p1->desc, p2->desc);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -868,9 +766,7 @@ static char * reset_disp_str(int r)
|
|||
}
|
||||
|
||||
|
||||
void avr_display(FILE * f, AVRPART * p, const char * prefix, int verbose)
|
||||
{
|
||||
int i;
|
||||
void avr_display(FILE *f, const AVRPART *p, const char *prefix, int verbose) {
|
||||
char * buf;
|
||||
const char * px;
|
||||
LNODEID ln;
|
||||
|
@ -905,23 +801,17 @@ void avr_display(FILE * f, AVRPART * p, const char * prefix, int verbose)
|
|||
fprintf( f, "%sMemory Detail :\n\n", prefix);
|
||||
|
||||
px = prefix;
|
||||
i = strlen(prefix) + 5;
|
||||
buf = (char *)malloc(i);
|
||||
if (buf == NULL) {
|
||||
/* ugh, this is not important enough to bail, just ignore it */
|
||||
}
|
||||
else {
|
||||
strcpy(buf, prefix);
|
||||
strcat(buf, " ");
|
||||
px = buf;
|
||||
}
|
||||
buf = (char *)cfg_malloc("avr_display()", strlen(prefix) + 5);
|
||||
strcpy(buf, prefix);
|
||||
strcat(buf, " ");
|
||||
px = buf;
|
||||
|
||||
if (verbose <= 2)
|
||||
avr_mem_display(px, f, NULL, p, verbose);
|
||||
|
||||
if (verbose <= 2) {
|
||||
avr_mem_display(px, f, NULL, p, 0, verbose);
|
||||
}
|
||||
for (ln=lfirst(p->mem); ln; ln=lnext(ln)) {
|
||||
m = ldata(ln);
|
||||
avr_mem_display(px, f, m, p, i, verbose);
|
||||
avr_mem_display(px, f, m, p, verbose);
|
||||
}
|
||||
|
||||
if (buf)
|
||||
|
|
71
src/config.c
71
src/config.c
|
@ -83,13 +83,24 @@ int init_config(void)
|
|||
void *cfg_malloc(const char *funcname, size_t n) {
|
||||
void *ret = malloc(n);
|
||||
if(!ret) {
|
||||
avrdude_message(MSG_INFO, "%s: out of memory in %s\n", progname, funcname);
|
||||
avrdude_message(MSG_INFO, "%s: out of memory in %s (needed %lu bytes)\n", progname, funcname, (unsigned long) n);
|
||||
exit(1);
|
||||
}
|
||||
memset(ret, 0, n);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *cfg_realloc(const char *funcname, void *p, size_t n) {
|
||||
void *ret;
|
||||
|
||||
if(!(ret = p? realloc(p, n): calloc(1, n))) {
|
||||
avrdude_message(MSG_INFO, "%s: out of memory in %s (needed %lu bytes)\n", progname, funcname, (unsigned long) n);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
char *cfg_strdup(const char *funcname, const char *s) {
|
||||
char *ret = strdup(s);
|
||||
|
@ -323,35 +334,45 @@ int read_config(const char * file)
|
|||
}
|
||||
|
||||
|
||||
// Linear-search cache for a few often-referenced strings
|
||||
const char *cache_string(const char *file) {
|
||||
static char **fnames;
|
||||
static int n=0;
|
||||
// Adapted version of a neat empirical hash function from comp.lang.c by Daniel Bernstein
|
||||
unsigned strhash(const char *str) {
|
||||
unsigned c, hash = 5381, n = 0;
|
||||
|
||||
if(!file)
|
||||
return NULL;
|
||||
while((c = (unsigned char) *str++) && n++ < 20)
|
||||
hash = 33*hash ^ c;
|
||||
|
||||
// Exists in cache?
|
||||
for(int i=0; i<n; i++)
|
||||
if(strcmp(fnames[i], file) == 0)
|
||||
return fnames[i];
|
||||
return hash;
|
||||
}
|
||||
|
||||
// Expand cache?
|
||||
if(n%128 == 0) {
|
||||
if(!(fnames = realloc(fnames, (n+128)*sizeof*fnames))) {
|
||||
yyerror("cache_string(): out of memory");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
fnames[n] = cfg_strdup("cache_string()", file);
|
||||
static char **hstrings[1<<12];
|
||||
|
||||
return fnames[n++];
|
||||
// Return a copy of the argument as hashed string
|
||||
const char *cache_string(const char *p) {
|
||||
int h, k;
|
||||
char **hs;
|
||||
|
||||
if(!p)
|
||||
p = "(NULL)";
|
||||
|
||||
h = strhash(p) % (sizeof hstrings/sizeof*hstrings);
|
||||
if(!(hs=hstrings[h]))
|
||||
hs = hstrings[h] = (char **) cfg_realloc("cache_string()", NULL, (16+1)*sizeof**hstrings);
|
||||
|
||||
for(k=0; hs[k]; k++)
|
||||
if(*p == *hs[k] && !strcmp(p, hs[k]))
|
||||
return hs[k];
|
||||
|
||||
if(k && k%16 == 0)
|
||||
hstrings[h] = (char **) cfg_realloc("cache_string()", hstrings[h], (k+16+1)*sizeof**hstrings);
|
||||
|
||||
hstrings[h][k+1]=NULL;
|
||||
|
||||
return hstrings[h][k] = cfg_strdup("cache_string()", p);
|
||||
}
|
||||
|
||||
// Captures comments during parsing
|
||||
int capture_comment_char(int c) {
|
||||
return c;
|
||||
void capture_comment_str(const char *p) {
|
||||
}
|
||||
|
||||
|
||||
|
@ -426,6 +447,12 @@ unsigned char *cfg_unescapeu(unsigned char *d, const unsigned char *s) {
|
|||
switch (*s) {
|
||||
case '\\':
|
||||
switch (*++s) {
|
||||
case '\n': // String continuation over new line
|
||||
#if '\n' != '\r'
|
||||
case '\r':
|
||||
#endif
|
||||
--d;
|
||||
break;
|
||||
case 'n':
|
||||
*d = '\n';
|
||||
break;
|
||||
|
|
|
@ -94,7 +94,7 @@ void print_token(TOKEN *tkn);
|
|||
|
||||
void pyytext(void);
|
||||
|
||||
int capture_comment_char(int c);
|
||||
void capture_comment_str(const char *str);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -308,10 +308,6 @@ prog_def :
|
|||
prog_decl :
|
||||
K_PROGRAMMER
|
||||
{ current_prog = pgm_new();
|
||||
if (current_prog == NULL) {
|
||||
yyerror("could not create pgm instance");
|
||||
YYABORT;
|
||||
}
|
||||
current_prog->config_file = cache_string(cfg_infile);
|
||||
current_prog->lineno = cfg_lineno;
|
||||
}
|
||||
|
@ -325,11 +321,6 @@ prog_decl :
|
|||
YYABORT;
|
||||
}
|
||||
current_prog = pgm_dup(pgm);
|
||||
if (current_prog == NULL) {
|
||||
yyerror("could not duplicate pgm instance");
|
||||
free_token($3);
|
||||
YYABORT;
|
||||
}
|
||||
current_prog->parent_id = cache_string($3->value.string);
|
||||
current_prog->config_file = cache_string(cfg_infile);
|
||||
current_prog->lineno = cfg_lineno;
|
||||
|
@ -400,10 +391,6 @@ part_decl :
|
|||
K_PART
|
||||
{
|
||||
current_part = avr_new_part();
|
||||
if (current_part == NULL) {
|
||||
yyerror("could not create part instance");
|
||||
YYABORT;
|
||||
}
|
||||
current_part->config_file = cache_string(cfg_infile);
|
||||
current_part->lineno = cfg_lineno;
|
||||
} |
|
||||
|
@ -417,11 +404,6 @@ part_decl :
|
|||
}
|
||||
|
||||
current_part = avr_dup_part(parent_part);
|
||||
if (current_part == NULL) {
|
||||
yyerror("could not duplicate part instance");
|
||||
free_token($3);
|
||||
YYABORT;
|
||||
}
|
||||
current_part->parent_id = cache_string($3->value.string);
|
||||
current_part->config_file = cache_string(cfg_infile);
|
||||
current_part->lineno = cfg_lineno;
|
||||
|
@ -465,8 +447,7 @@ prog_parm :
|
|||
prog_parm_conntype
|
||||
|
|
||||
K_DESC TKN_EQUAL TKN_STRING {
|
||||
strncpy(current_prog->desc, $3->value.string, PGM_DESCLEN);
|
||||
current_prog->desc[PGM_DESCLEN-1] = 0;
|
||||
current_prog->desc = cache_string($3->value.string);
|
||||
free_token($3);
|
||||
} |
|
||||
K_BAUDRATE TKN_EQUAL TKN_NUMBER {
|
||||
|
@ -686,22 +667,19 @@ retry_lines :
|
|||
part_parm :
|
||||
K_ID TKN_EQUAL TKN_STRING
|
||||
{
|
||||
strncpy(current_part->id, $3->value.string, AVR_IDLEN);
|
||||
current_part->id[AVR_IDLEN-1] = 0;
|
||||
current_part->id = cache_string($3->value.string);
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_DESC TKN_EQUAL TKN_STRING
|
||||
{
|
||||
strncpy(current_part->desc, $3->value.string, AVR_DESCLEN - 1);
|
||||
current_part->desc[AVR_DESCLEN-1] = 0;
|
||||
current_part->desc = cache_string($3->value.string);
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_FAMILY_ID TKN_EQUAL TKN_STRING
|
||||
{
|
||||
strncpy(current_part->family_id, $3->value.string, AVR_FAMILYIDLEN);
|
||||
current_part->family_id[AVR_FAMILYIDLEN] = 0;
|
||||
current_part->family_id = cache_string($3->value.string);
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
|
@ -1289,13 +1267,8 @@ part_parm :
|
|||
{ /* select memory for extension or create if not there */
|
||||
AVRMEM *mem = avr_locate_mem_noalias(current_part, $2->value.string);
|
||||
if(!mem) {
|
||||
if(!(mem = avr_new_memtype())) {
|
||||
yyerror("could not create mem instance");
|
||||
free_token($2);
|
||||
YYABORT;
|
||||
}
|
||||
strncpy(mem->desc, $2->value.string, AVR_MEMDESCLEN - 1);
|
||||
mem->desc[AVR_MEMDESCLEN-1] = 0;
|
||||
mem = avr_new_memtype();
|
||||
mem->desc = cache_string($2->value.string);
|
||||
ladd(current_part->mem, mem);
|
||||
}
|
||||
avr_add_mem_order($2->value.string);
|
||||
|
@ -1339,11 +1312,6 @@ part_parm :
|
|||
opnum = which_opcode($1);
|
||||
if (opnum < 0) YYABORT;
|
||||
op = avr_new_opcode();
|
||||
if (op == NULL) {
|
||||
yyerror("could not create opcode instance");
|
||||
free_token($1);
|
||||
YYABORT;
|
||||
}
|
||||
if(0 != parse_cmdbits(op, opnum))
|
||||
YYABORT;
|
||||
if (current_part->op[opnum] != NULL) {
|
||||
|
@ -1500,11 +1468,6 @@ mem_spec :
|
|||
opnum = which_opcode($1);
|
||||
if (opnum < 0) YYABORT;
|
||||
op = avr_new_opcode();
|
||||
if (op == NULL) {
|
||||
yyerror("could not create opcode instance");
|
||||
free_token($1);
|
||||
YYABORT;
|
||||
}
|
||||
if(0 != parse_cmdbits(op, opnum))
|
||||
YYABORT;
|
||||
if (current_mem->op[opnum] != NULL) {
|
||||
|
@ -1553,10 +1516,7 @@ mem_alias :
|
|||
|
||||
is_alias = true;
|
||||
alias = avr_new_memalias();
|
||||
|
||||
// alias->desc and current_mem->desc have the same length
|
||||
// definition, thus no need to check for length here
|
||||
strcpy(alias->desc, current_mem->desc);
|
||||
alias->desc = current_mem->desc;
|
||||
alias->aliased_mem = existing_mem;
|
||||
ladd(current_part->mem_alias, alias);
|
||||
|
||||
|
|
|
@ -222,7 +222,7 @@ int dev_message(int msglvl, const char *fmt, ...) {
|
|||
|
||||
|
||||
|
||||
static int dev_part_strct_entry(bool tsv, char *col0, char *col1, char *col2, const char *name, char *cont) {
|
||||
static int dev_part_strct_entry(bool tsv, const char *col0, const char *col1, const char *col2, const char *name, char *cont) {
|
||||
const char *n = name? name: "name_error";
|
||||
const char *c = cont? cont: "cont_error";
|
||||
|
||||
|
@ -286,23 +286,22 @@ static int intcmp(int a, int b) {
|
|||
// Deep copies for comparison and raw output
|
||||
|
||||
typedef struct {
|
||||
char descbuf[32];
|
||||
AVRMEM base;
|
||||
OPCODE ops[AVR_OP_MAX];
|
||||
} AVRMEMdeep;
|
||||
|
||||
static int avrmem_deep_copy(AVRMEMdeep *d, AVRMEM *m) {
|
||||
size_t len;
|
||||
|
||||
d->base = *m;
|
||||
|
||||
// Zap all bytes beyond terminating nul of desc array
|
||||
len = strlen(m->desc)+1;
|
||||
if(len < sizeof m->desc)
|
||||
memset(d->base.desc + len, 0, sizeof m->desc - len);
|
||||
// Note memory desc (name, really) is limited to 31 char here
|
||||
memset(d->descbuf, 0, sizeof d->descbuf);
|
||||
strncpy(d->descbuf, m->desc, sizeof d->descbuf-1);
|
||||
|
||||
// Zap address values
|
||||
d->base.buf = NULL;
|
||||
d->base.tags = NULL;
|
||||
d->base.desc = NULL;
|
||||
for(int i=0; i<AVR_OP_MAX; i++)
|
||||
d->base.op[i] = NULL;
|
||||
|
||||
|
@ -334,6 +333,9 @@ static int memorycmp(AVRMEM *m1, AVRMEM *m2) {
|
|||
|
||||
|
||||
typedef struct {
|
||||
char descbuf[64];
|
||||
char idbuf[32];
|
||||
char family_idbuf[16];
|
||||
AVRPART base;
|
||||
OPCODE ops[AVR_OP_MAX];
|
||||
AVRMEMdeep mems[40];
|
||||
|
@ -341,7 +343,7 @@ typedef struct {
|
|||
|
||||
static int avrpart_deep_copy(AVRPARTdeep *d, AVRPART *p) {
|
||||
AVRMEM *m;
|
||||
size_t len, di;
|
||||
size_t di;
|
||||
|
||||
memset(d, 0, sizeof *d);
|
||||
|
||||
|
@ -351,20 +353,21 @@ static int avrpart_deep_copy(AVRPARTdeep *d, AVRPART *p) {
|
|||
d->base.config_file = NULL;
|
||||
d->base.lineno = 0;
|
||||
|
||||
// Zap all bytes beyond terminating nul of desc, id and family_id array
|
||||
len = strlen(p->desc);
|
||||
if(len < sizeof p->desc)
|
||||
memset(d->base.desc + len, 0, sizeof p->desc - len);
|
||||
|
||||
len = strlen(p->family_id);
|
||||
if(len < sizeof p->family_id)
|
||||
memset(d->base.family_id + len, 0, sizeof p->family_id - len);
|
||||
|
||||
len = strlen(p->id);
|
||||
if(len < sizeof p->id)
|
||||
memset(d->base.id + len, 0, sizeof p->id - len);
|
||||
// Copy over desc, id, and family_id
|
||||
memset(d->descbuf, 0, sizeof d->descbuf);
|
||||
if(d->descbuf)
|
||||
strncpy(d->descbuf, p->desc, sizeof d->descbuf-1);
|
||||
memset(d->idbuf, 0, sizeof d->idbuf);
|
||||
if(d->idbuf)
|
||||
strncpy(d->idbuf, p->id, sizeof d->idbuf-1);
|
||||
memset(d->family_idbuf, 0, sizeof d->family_idbuf);
|
||||
if(d->family_idbuf)
|
||||
strncpy(d->family_idbuf, p->family_id, sizeof d->family_idbuf-1);
|
||||
|
||||
// Zap address values
|
||||
d->base.desc = NULL;
|
||||
d->base.id = NULL;
|
||||
d->base.family_id = NULL;
|
||||
d->base.mem = NULL;
|
||||
d->base.mem_alias = NULL;
|
||||
for(int i=0; i<AVR_OP_MAX; i++)
|
||||
|
@ -397,14 +400,14 @@ static int avrpart_deep_copy(AVRPARTdeep *d, AVRPART *p) {
|
|||
|
||||
static char txtchar(unsigned char in) {
|
||||
in &= 0x7f;
|
||||
return in == ' '? '_': in > ' ' && in < 0x7f? in: '.';
|
||||
return in == 0? '.': in > ' ' && in < 0x7f? in: '_';
|
||||
}
|
||||
|
||||
static void dev_raw_dump(const char *p, int nbytes, const char *name, const char *sub, int idx) {
|
||||
int n = (nbytes + 31)/32;
|
||||
|
||||
for(int i=0; i<n; i++, p += 32, nbytes -= 32) {
|
||||
dev_info("%s\t%s\t%02x%03x0: ", name, sub, idx, 2*i);
|
||||
dev_info("%s\t%s\t%02x.%03x0: ", name, sub, idx, 2*i);
|
||||
for(int j=0; j<32; j++) {
|
||||
if(j && j%8 == 0)
|
||||
dev_info(" ");
|
||||
|
@ -429,7 +432,7 @@ static void dev_part_raw(AVRPART *part) {
|
|||
dev_raw_dump((char *) &dp.ops, sizeof dp.ops, part->desc, "ops", 1);
|
||||
|
||||
for(int i=0; i<di; i++)
|
||||
dev_raw_dump((char *) (dp.mems+i), sizeof dp.mems[i], part->desc, dp.mems[i].base.desc, i+2);
|
||||
dev_raw_dump((char *) (dp.mems+i), sizeof dp.mems[i], part->desc, dp.mems[i].descbuf, i+2);
|
||||
}
|
||||
|
||||
|
||||
|
@ -680,7 +683,10 @@ void dev_output_part_defs(char *partdesc) {
|
|||
avr_add_mem_order(((AVRMEM_ALIAS *) ldata(lnm))->desc);
|
||||
}
|
||||
|
||||
nprinted = dev_nprinted;
|
||||
if((nprinted = dev_nprinted)) {
|
||||
dev_info("\n");
|
||||
nprinted = dev_nprinted;
|
||||
}
|
||||
for(LNODEID ln1 = lfirst(part_list); ln1; ln1 = lnext(ln1)) {
|
||||
AVRPART *p = ldata(ln1);
|
||||
int flashsize, flashoffset, flashpagesize, eepromsize , eepromoffset, eeprompagesize;
|
||||
|
@ -914,6 +920,8 @@ static void dev_pgm_raw(PROGRAMMER *pgm) {
|
|||
for(idx=0, ln=lfirst(dp.hvupdi_support); ln; ln=lnext(ln))
|
||||
dev_raw_dump(ldata(ln), sizeof(int), id, "hvupdi_", idx++);
|
||||
|
||||
if(dp.desc)
|
||||
dev_raw_dump(dp.desc, strlen(dp.desc)+1, id, "desc", 0);
|
||||
// Dump cache_string values
|
||||
if(dp.usbdev && *dp.usbdev)
|
||||
dev_raw_dump(dp.usbdev, strlen(dp.usbdev)+1, id, "usbdev", 0);
|
||||
|
@ -925,14 +933,13 @@ static void dev_pgm_raw(PROGRAMMER *pgm) {
|
|||
dev_raw_dump(dp.usbproduct, strlen(dp.usbproduct)+1, id, "usbprod", 0);
|
||||
|
||||
// Zap all bytes beyond terminating nul of desc, type and port array
|
||||
if((len = strlen(dp.desc)+1) < sizeof dp.desc)
|
||||
memset(dp.desc + len, 0, sizeof dp.desc - len);
|
||||
if((len = strlen(dp.type)+1) < sizeof dp.type)
|
||||
memset(dp.type + len, 0, sizeof dp.type - len);
|
||||
if((len = strlen(dp.port)+1) < sizeof dp.port)
|
||||
memset(dp.port + len, 0, sizeof dp.port - len);
|
||||
|
||||
// Zap address values
|
||||
dp.desc = NULL;
|
||||
dp.id = NULL;
|
||||
dp.parent_id = NULL;
|
||||
dp.initpgm = NULL;
|
||||
|
|
|
@ -609,7 +609,7 @@ static int jtagmkI_initialize(PROGRAMMER * pgm, AVRPART * p)
|
|||
if (jtagmkI_reset(pgm) < 0)
|
||||
return -1;
|
||||
|
||||
strcpy(hfuse.desc, "hfuse");
|
||||
hfuse.desc = cache_string("hfuse");
|
||||
if (jtagmkI_read_byte(pgm, p, &hfuse, 1, &b) < 0)
|
||||
return -1;
|
||||
if ((b & OCDEN) != 0)
|
||||
|
|
|
@ -1439,7 +1439,7 @@ static int jtagmkII_initialize(PROGRAMMER * pgm, AVRPART * p)
|
|||
}
|
||||
|
||||
if ((pgm->flag & PGM_FL_IS_JTAG) && !(p->flags & (AVRPART_HAS_PDI | AVRPART_HAS_UPDI))) {
|
||||
strcpy(hfuse.desc, "hfuse");
|
||||
hfuse.desc = cache_string("hfuse");
|
||||
if (jtagmkII_read_byte(pgm, p, &hfuse, 1, &b) < 0)
|
||||
return -1;
|
||||
if ((b & OCDEN) != 0)
|
||||
|
|
10
src/lexer.l
10
src/lexer.l
|
@ -45,8 +45,6 @@ DIGIT [0-9]
|
|||
HEXDIGIT [0-9a-fA-F]
|
||||
SIGN [+-]
|
||||
|
||||
%x incl
|
||||
%x comment
|
||||
%option nounput
|
||||
|
||||
/* Bump resources for classic lex. */
|
||||
|
@ -73,16 +71,12 @@ SIGN [+-]
|
|||
|
||||
0x{HEXDIGIT}+ { yylval = hexnumber(yytext); return TKN_NUMBER; }
|
||||
|
||||
# { /* The following captures all '#' style comments to end of line */
|
||||
BEGIN(comment); }
|
||||
<comment>[^\n]*\n+ { /* eat comments */
|
||||
capture_comment_char('#');
|
||||
#[^\n]*\n+ { /* record and skip # comments */
|
||||
capture_comment_str(yytext);
|
||||
for(int i=0; yytext[i]; i++) {
|
||||
capture_comment_char(yytext[i]);
|
||||
if(yytext[i] == '\n')
|
||||
cfg_lineno++;
|
||||
}
|
||||
BEGIN(INITIAL);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -203,8 +203,6 @@ typedef struct opcode {
|
|||
#define HV_UPDI_VARIANT_1 1 /* Dedicated UPDI pin, no HV (megaAVR0/AVR-Dx) */
|
||||
#define HV_UPDI_VARIANT_2 2 /* Shared UPDI pin, HV on _RESET (AVR-Ex) */
|
||||
|
||||
#define AVR_DESCLEN 64
|
||||
#define AVR_IDLEN 32
|
||||
#define AVR_FAMILYIDLEN 7
|
||||
#define AVR_SIBLEN 16
|
||||
#define CTL_STACK_SIZE 32
|
||||
|
@ -215,10 +213,10 @@ typedef struct opcode {
|
|||
|
||||
/* Any changes here, please also reflect in dev_part_strct() of developer_opts.c */
|
||||
typedef struct avrpart {
|
||||
char desc[AVR_DESCLEN]; /* long part name */
|
||||
char id[AVR_IDLEN]; /* short part name */
|
||||
const char * desc; /* long part name */
|
||||
const char * id; /* short part name */
|
||||
const char * parent_id; /* parent id if set, for -p.../s */
|
||||
char family_id[AVR_FAMILYIDLEN+1]; /* family id in the SIB (avr8x) */
|
||||
const char * family_id; /* family id in the SIB (avr8x) */
|
||||
int hvupdi_variant; /* HV pulse on UPDI pin, no pin or RESET pin */
|
||||
int stk500_devcode; /* stk500 device code */
|
||||
int avr910_devcode; /* avr910 device code */
|
||||
|
@ -286,7 +284,7 @@ typedef struct avrpart {
|
|||
|
||||
#define AVR_MEMDESCLEN 64
|
||||
typedef struct avrmem {
|
||||
char desc[AVR_MEMDESCLEN]; /* memory description ("flash", "eeprom", etc) */
|
||||
const char *desc; /* memory description ("flash", "eeprom", etc) */
|
||||
int paged; /* page addressed (e.g. ATmega flash) */
|
||||
int size; /* total memory size in bytes */
|
||||
int page_size; /* size of memory page (if page addressed) */
|
||||
|
@ -312,7 +310,7 @@ typedef struct avrmem {
|
|||
} AVRMEM;
|
||||
|
||||
typedef struct avrmem_alias {
|
||||
char desc[AVR_MEMDESCLEN]; /* alias name ("syscfg0" etc.) */
|
||||
const char *desc; /* alias name ("syscfg0" etc.) */
|
||||
AVRMEM *aliased_mem;
|
||||
} AVRMEM_ALIAS;
|
||||
|
||||
|
@ -330,8 +328,8 @@ int avr_set_bits(OPCODE * op, unsigned char * cmd);
|
|||
int avr_set_addr(OPCODE * op, unsigned char * cmd, unsigned long addr);
|
||||
int avr_set_addr_mem(AVRMEM *mem, int opnum, unsigned char *cmd, unsigned long addr);
|
||||
int avr_set_input(OPCODE * op, unsigned char * cmd, unsigned char data);
|
||||
int avr_get_output(OPCODE * op, unsigned char * res, unsigned char * data);
|
||||
int avr_get_output_index(OPCODE * op);
|
||||
int avr_get_output(const OPCODE *op, const unsigned char *res, unsigned char *data);
|
||||
int avr_get_output_index(const OPCODE *op);
|
||||
char cmdbitchar(CMDBIT cb);
|
||||
char *cmdbitstr(CMDBIT cb);
|
||||
const char *opcodename(int opnum);
|
||||
|
@ -340,26 +338,26 @@ char *opcode2str(OPCODE *op, int opnum, int detailed);
|
|||
/* Functions for AVRMEM structures */
|
||||
AVRMEM * avr_new_memtype(void);
|
||||
AVRMEM_ALIAS * avr_new_memalias(void);
|
||||
int avr_initmem(AVRPART * p);
|
||||
AVRMEM * avr_dup_mem(AVRMEM * m);
|
||||
int avr_initmem(const AVRPART *p);
|
||||
AVRMEM * avr_dup_mem(const AVRMEM *m);
|
||||
void avr_free_mem(AVRMEM * m);
|
||||
void avr_free_memalias(AVRMEM_ALIAS * m);
|
||||
AVRMEM * avr_locate_mem(AVRPART * p, const char * desc);
|
||||
AVRMEM * avr_locate_mem_noalias(AVRPART * p, const char * desc);
|
||||
AVRMEM_ALIAS * avr_locate_memalias(AVRPART * p, const char * desc);
|
||||
AVRMEM_ALIAS * avr_find_memalias(AVRPART * p, AVRMEM * m_orig);
|
||||
void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, AVRPART * p,
|
||||
int type, int verbose);
|
||||
AVRMEM * avr_locate_mem(const AVRPART *p, const char *desc);
|
||||
AVRMEM * avr_locate_mem_noalias(const AVRPART *p, const char *desc);
|
||||
AVRMEM_ALIAS * avr_locate_memalias(const AVRPART *p, const char *desc);
|
||||
AVRMEM_ALIAS * avr_find_memalias(const AVRPART *p, const AVRMEM *m_orig);
|
||||
void avr_mem_display(const char *prefix, FILE *f, const AVRMEM *m,
|
||||
const AVRPART *p, int verbose);
|
||||
|
||||
/* Functions for AVRPART structures */
|
||||
AVRPART * avr_new_part(void);
|
||||
AVRPART * avr_dup_part(AVRPART * d);
|
||||
AVRPART * avr_dup_part(const AVRPART *d);
|
||||
void avr_free_part(AVRPART * d);
|
||||
AVRPART * locate_part(LISTID parts, const char * partdesc);
|
||||
AVRPART * locate_part_by_avr910_devcode(LISTID parts, int devcode);
|
||||
AVRPART * locate_part_by_signature(LISTID parts, unsigned char * sig,
|
||||
AVRPART * locate_part(const LISTID parts, const char *partdesc);
|
||||
AVRPART * locate_part_by_avr910_devcode(const LISTID parts, int devcode);
|
||||
AVRPART * locate_part_by_signature(const LISTID parts, unsigned char *sig,
|
||||
int sigsize);
|
||||
void avr_display(FILE * f, AVRPART * p, const char * prefix, int verbose);
|
||||
void avr_display(FILE *f, const AVRPART *p, const char *prefix, int verbose);
|
||||
|
||||
typedef void (*walk_avrparts_cb)(const char *name, const char *desc,
|
||||
const char *cfgname, int cfglineno,
|
||||
|
@ -653,7 +651,6 @@ extern struct serial_device usbhid_serdev;
|
|||
#define ON 1
|
||||
#define OFF 0
|
||||
|
||||
#define PGM_DESCLEN 80
|
||||
#define PGM_PORTLEN PATH_MAX
|
||||
#define PGM_TYPELEN 32
|
||||
|
||||
|
@ -685,7 +682,7 @@ typedef enum {
|
|||
/* Any changes here, please also reflect in dev_pgm_strct() of developer_opts.c */
|
||||
typedef struct programmer_t {
|
||||
LISTID id;
|
||||
char desc[PGM_DESCLEN];
|
||||
const char *desc;
|
||||
void (*initpgm)(struct programmer_t *pgm);
|
||||
const char *parent_id; // Used by developer options -c*/[sr...]
|
||||
struct pindef_t pin[N_PINS];
|
||||
|
@ -762,6 +759,7 @@ typedef struct programmer_t {
|
|||
int (*parseextparams) (struct programmer_t * pgm, LISTID xparams);
|
||||
void (*setup) (struct programmer_t * pgm);
|
||||
void (*teardown) (struct programmer_t * pgm);
|
||||
|
||||
const char *config_file; // Config file where defined
|
||||
int lineno; // Config file line number
|
||||
void *cookie; // For private use by the programmer
|
||||
|
@ -773,8 +771,8 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
PROGRAMMER * pgm_new(void);
|
||||
PROGRAMMER * pgm_dup(const PROGRAMMER * const src);
|
||||
void pgm_free(PROGRAMMER * const p);
|
||||
PROGRAMMER * pgm_dup(const PROGRAMMER *src);
|
||||
void pgm_free(PROGRAMMER *p);
|
||||
|
||||
void programmer_display(PROGRAMMER * pgm, const char * p);
|
||||
|
||||
|
@ -783,10 +781,10 @@ void programmer_display(PROGRAMMER * pgm, const char * p);
|
|||
#define SHOW_PPI_PINS ((1<<PPI_AVR_VCC)|(1<<PPI_AVR_BUFF))
|
||||
#define SHOW_AVR_PINS ((1<<PIN_AVR_RESET)|(1<<PIN_AVR_SCK)|(1<<PIN_AVR_MOSI)|(1<<PIN_AVR_MISO))
|
||||
#define SHOW_LED_PINS ((1<<PIN_LED_ERR)|(1<<PIN_LED_RDY)|(1<<PIN_LED_PGM)|(1<<PIN_LED_VFY))
|
||||
void pgm_display_generic_mask(PROGRAMMER * pgm, const char * p, unsigned int show);
|
||||
void pgm_display_generic(PROGRAMMER * pgm, const char * p);
|
||||
void pgm_display_generic_mask(const PROGRAMMER *pgm, const char *p, unsigned int show);
|
||||
void pgm_display_generic(const PROGRAMMER *pgm, const char *p);
|
||||
|
||||
PROGRAMMER * locate_programmer(LISTID programmers, const char * configid);
|
||||
PROGRAMMER *locate_programmer(const LISTID programmers, const char *configid);
|
||||
|
||||
typedef void (*walk_programmers_cb)(const char *name, const char *desc,
|
||||
const char *cfgname, int cfglineno,
|
||||
|
|
10
src/main.c
10
src/main.c
|
@ -1073,9 +1073,9 @@ int main(int argc, char * argv [])
|
|||
pgm->read_sib(pgm, p, sib);
|
||||
avrdude_message(MSG_NOTICE, "%s: System Information Block: \"%s\"\n",
|
||||
progname, sib);
|
||||
if (quell_progress < 2) {
|
||||
if (quell_progress < 2)
|
||||
avrdude_message(MSG_INFO, "%s: Received FamilyID: \"%.*s\"\n", progname, AVR_FAMILYIDLEN, sib);
|
||||
}
|
||||
|
||||
if (strncmp(p->family_id, sib, AVR_FAMILYIDLEN)) {
|
||||
avrdude_message(MSG_INFO, "%s: Expected FamilyID: \"%s\"\n", progname, p->family_id);
|
||||
if (!ovsigck) {
|
||||
|
@ -1093,9 +1093,8 @@ int main(int argc, char * argv [])
|
|||
avrdude_message(MSG_INFO, "%s: conflicting -e and -n options specified, NOT erasing chip\n",
|
||||
progname);
|
||||
} else {
|
||||
if (quell_progress < 2) {
|
||||
if (quell_progress < 2)
|
||||
avrdude_message(MSG_INFO, "%s: erasing chip\n", progname);
|
||||
}
|
||||
exitrc = avr_unlock(pgm, p);
|
||||
if(exitrc) goto main_exit;
|
||||
goto sig_again;
|
||||
|
@ -1229,9 +1228,8 @@ int main(int argc, char * argv [])
|
|||
avrdude_message(MSG_INFO, "%s: conflicting -e and -n options specified, NOT erasing chip\n",
|
||||
progname);
|
||||
} else {
|
||||
if (quell_progress < 2) {
|
||||
if (quell_progress < 2)
|
||||
avrdude_message(MSG_INFO, "%s: erasing chip\n", progname);
|
||||
}
|
||||
exitrc = avr_chip_erase(pgm, p);
|
||||
if(exitrc) goto main_exit;
|
||||
}
|
||||
|
|
137
src/pgm.c
137
src/pgm.c
|
@ -61,31 +61,29 @@ static void pgm_default_powerup_powerdown (struct programmer_t * pgm)
|
|||
}
|
||||
|
||||
|
||||
PROGRAMMER * pgm_new(void)
|
||||
{
|
||||
int i;
|
||||
PROGRAMMER * pgm;
|
||||
PROGRAMMER *pgm_new(void) {
|
||||
PROGRAMMER *pgm = (PROGRAMMER *) cfg_malloc("pgm_new()", sizeof(*pgm));
|
||||
const char *nulp = cache_string("");
|
||||
|
||||
pgm = (PROGRAMMER *) cfg_malloc("pgm_new()", sizeof(*pgm));
|
||||
|
||||
// Initialise const char * and LISTID entities
|
||||
pgm->id = lcreat(NULL, 0);
|
||||
pgm->usbpid = lcreat(NULL, 0);
|
||||
pgm->desc[0] = 0;
|
||||
pgm->type[0] = 0;
|
||||
pgm->parent_id = nulp;
|
||||
pgm->config_file = nulp;
|
||||
pgm->lineno = 0;
|
||||
pgm->baudrate = 0;
|
||||
pgm->initpgm = NULL;
|
||||
pgm->hvupdi_support = lcreat(NULL, 0);
|
||||
|
||||
pgm->desc = nulp;
|
||||
pgm->parent_id = nulp;
|
||||
pgm->usbdev = nulp;
|
||||
pgm->usbsn = nulp;
|
||||
pgm->usbvendor = nulp;
|
||||
pgm->usbproduct = nulp;
|
||||
pgm->config_file = nulp;
|
||||
|
||||
for (i=0; i<N_PINS; i++) {
|
||||
// Default values
|
||||
pgm->initpgm = NULL;
|
||||
pgm->lineno = 0;
|
||||
pgm->baudrate = 0;
|
||||
|
||||
// Clear pin array
|
||||
for(int i=0; i<N_PINS; i++) {
|
||||
pgm->pinno[i] = 0;
|
||||
pin_clear_all(&(pgm->pin[i]));
|
||||
}
|
||||
|
@ -121,49 +119,70 @@ PROGRAMMER * pgm_new(void)
|
|||
* optional functions - these are checked to make sure they are
|
||||
* assigned before they are called
|
||||
*/
|
||||
pgm->unlock = NULL;
|
||||
pgm->cmd = NULL;
|
||||
pgm->cmd_tpi = NULL;
|
||||
pgm->spi = NULL;
|
||||
pgm->paged_write = NULL;
|
||||
pgm->paged_load = NULL;
|
||||
pgm->page_erase = NULL;
|
||||
pgm->write_setup = NULL;
|
||||
pgm->read_sig_bytes = NULL;
|
||||
pgm->read_sib = NULL;
|
||||
pgm->print_parms = NULL;
|
||||
pgm->set_vtarget = NULL;
|
||||
pgm->set_varef = NULL;
|
||||
pgm->set_fosc = NULL;
|
||||
pgm->set_sck_period = NULL;
|
||||
pgm->setpin = NULL;
|
||||
pgm->getpin = NULL;
|
||||
pgm->highpulsepin = NULL;
|
||||
pgm->parseexitspecs = NULL;
|
||||
pgm->perform_osccal = NULL;
|
||||
pgm->parseextparams = NULL;
|
||||
pgm->setup = NULL;
|
||||
pgm->teardown = NULL;
|
||||
|
||||
// For allocating "global" memory by the programmer
|
||||
pgm->cookie = NULL;
|
||||
|
||||
return pgm;
|
||||
}
|
||||
|
||||
void pgm_free(PROGRAMMER * const p)
|
||||
{
|
||||
ldestroy_cb(p->id, free);
|
||||
ldestroy_cb(p->usbpid, free);
|
||||
p->id = NULL;
|
||||
p->usbpid = NULL;
|
||||
/* do not free p->parent_id, p->config_file, p->usbdev, p->usbsn, p->usbvendor or p-> usbproduct */
|
||||
/* p->cookie is freed by pgm_teardown */
|
||||
free(p);
|
||||
void pgm_free(PROGRAMMER *p) {
|
||||
if(p) {
|
||||
ldestroy_cb(p->id, free);
|
||||
ldestroy_cb(p->usbpid, free);
|
||||
ldestroy_cb(p->hvupdi_support, free);
|
||||
p->id = NULL;
|
||||
p->usbpid = NULL;
|
||||
p->hvupdi_support = NULL;
|
||||
// Never free const char *, eg, p->desc, which are set by cache_string()
|
||||
// p->cookie is freed by pgm_teardown
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
|
||||
PROGRAMMER * pgm_dup(const PROGRAMMER * const src)
|
||||
{
|
||||
PROGRAMMER * pgm;
|
||||
LNODEID ln;
|
||||
PROGRAMMER *pgm_dup(const PROGRAMMER *src) {
|
||||
PROGRAMMER *pgm = pgm_new();
|
||||
|
||||
pgm = (PROGRAMMER *) cfg_malloc("pgm_dup()", sizeof(*pgm));
|
||||
memcpy(pgm, src, sizeof(*pgm));
|
||||
if(src) {
|
||||
memcpy(pgm, src, sizeof(*pgm));
|
||||
pgm->id = lcreat(NULL, 0);
|
||||
pgm->usbpid = lcreat(NULL, 0);
|
||||
pgm->hvupdi_support = lcreat(NULL, 0);
|
||||
|
||||
pgm->id = lcreat(NULL, 0);
|
||||
pgm->usbpid = lcreat(NULL, 0);
|
||||
for (ln = lfirst(src->usbpid); ln; ln = lnext(ln)) {
|
||||
int *ip = cfg_malloc("pgm_dup()", sizeof(int));
|
||||
*ip = *(int *) ldata(ln);
|
||||
ladd(pgm->usbpid, ip);
|
||||
// Leave id list empty but copy usbpid and hvupdi_support over
|
||||
for(LNODEID ln = lfirst(src->hvupdi_support); ln; ln = lnext(ln)) {
|
||||
int *ip = cfg_malloc("pgm_dup()", sizeof(int));
|
||||
*ip = *(int *) ldata(ln);
|
||||
ladd(pgm->hvupdi_support, ip);
|
||||
}
|
||||
for(LNODEID ln = lfirst(src->usbpid); ln; ln = lnext(ln)) {
|
||||
int *ip = cfg_malloc("pgm_dup()", sizeof(int));
|
||||
*ip = *(int *) ldata(ln);
|
||||
ladd(pgm->usbpid, ip);
|
||||
}
|
||||
}
|
||||
|
||||
return pgm;
|
||||
|
@ -207,8 +226,7 @@ static void pgm_default_6 (struct programmer_t * pgm, const char * p)
|
|||
}
|
||||
|
||||
|
||||
void programmer_display(PROGRAMMER * pgm, const char * p)
|
||||
{
|
||||
void programmer_display(PROGRAMMER *pgm, const char * p) {
|
||||
avrdude_message(MSG_INFO, "%sProgrammer Type : %s\n", p, pgm->type);
|
||||
avrdude_message(MSG_INFO, "%sDescription : %s\n", p, pgm->desc);
|
||||
|
||||
|
@ -216,8 +234,7 @@ void programmer_display(PROGRAMMER * pgm, const char * p)
|
|||
}
|
||||
|
||||
|
||||
void pgm_display_generic_mask(PROGRAMMER * pgm, const char * p, unsigned int show)
|
||||
{
|
||||
void pgm_display_generic_mask(const PROGRAMMER *pgm, const char *p, unsigned int show) {
|
||||
if(show & (1<<PPI_AVR_VCC))
|
||||
avrdude_message(MSG_INFO, "%s VCC = %s\n", p, pins_to_str(&pgm->pin[PPI_AVR_VCC]));
|
||||
if(show & (1<<PPI_AVR_BUFF))
|
||||
|
@ -240,33 +257,22 @@ void pgm_display_generic_mask(PROGRAMMER * pgm, const char * p, unsigned int sho
|
|||
avrdude_message(MSG_INFO, "%s VFY LED = %s\n", p, pins_to_str(&pgm->pin[PIN_LED_VFY]));
|
||||
}
|
||||
|
||||
void pgm_display_generic(PROGRAMMER * pgm, const char * p)
|
||||
{
|
||||
void pgm_display_generic(const PROGRAMMER *pgm, const char *p) {
|
||||
pgm_display_generic_mask(pgm, p, SHOW_ALL_PINS);
|
||||
}
|
||||
|
||||
PROGRAMMER * locate_programmer(LISTID programmers, const char * configid)
|
||||
{
|
||||
LNODEID ln1, ln2;
|
||||
PROGRAMMER * p = NULL;
|
||||
const char * id;
|
||||
int found;
|
||||
PROGRAMMER *locate_programmer(const LISTID programmers, const char *configid) {
|
||||
PROGRAMMER *p = NULL;
|
||||
int found = 0;
|
||||
|
||||
found = 0;
|
||||
|
||||
for (ln1=lfirst(programmers); ln1 && !found; ln1=lnext(ln1)) {
|
||||
for(LNODEID ln1=lfirst(programmers); ln1 && !found; ln1=lnext(ln1)) {
|
||||
p = ldata(ln1);
|
||||
for (ln2=lfirst(p->id); ln2 && !found; ln2=lnext(ln2)) {
|
||||
id = ldata(ln2);
|
||||
if (strcasecmp(configid, id) == 0)
|
||||
for(LNODEID ln2=lfirst(p->id); ln2 && !found; ln2=lnext(ln2))
|
||||
if(strcasecmp(configid, (const char *) ldata(ln2)) == 0)
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
return p;
|
||||
|
||||
return NULL;
|
||||
return found? p: NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -296,16 +302,11 @@ void walk_programmers(LISTID programmers, walk_programmers_cb cb, void *cookie)
|
|||
/*
|
||||
* Compare function to sort the list of programmers
|
||||
*/
|
||||
static int sort_programmer_compare(PROGRAMMER * p1,PROGRAMMER * p2)
|
||||
{
|
||||
char* id1;
|
||||
char* id2;
|
||||
if(p1 == NULL || p2 == NULL) {
|
||||
static int sort_programmer_compare(const PROGRAMMER *p1, const PROGRAMMER *p2) {
|
||||
if(p1 == NULL || p1->id == NULL || p2 == NULL || p2->id == NULL)
|
||||
return 0;
|
||||
}
|
||||
id1 = ldata(lfirst(p1->id));
|
||||
id2 = ldata(lfirst(p2->id));
|
||||
return strncasecmp(id1,id2,AVR_IDLEN);
|
||||
|
||||
return strcasecmp(ldata(lfirst(p1->id)), ldata(lfirst(p2->id)));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -193,16 +193,18 @@ static int pickit2_open(PROGRAMMER * pgm, char * port)
|
|||
}
|
||||
else
|
||||
{
|
||||
// get the device description while we're at it
|
||||
short buff[PGM_DESCLEN-1], i;
|
||||
HidD_GetProductString(PDATA(pgm)->usb_handle, buff, PGM_DESCLEN-1);
|
||||
// Get the device description while we're at it and overlay it on pgm->desc
|
||||
short wbuf[80-1];
|
||||
char *cbuf = cfg_malloc("pickit2_open()", sizeof wbuf/sizeof*wbuf + (pgm->desc? strlen(pgm->desc): 0) + 2);
|
||||
HidD_GetProductString(PDATA(pgm)->usb_handle, wbuf, sizeof wbuf/sizeof*wbuf);
|
||||
|
||||
// convert from wide chars, but do not overwrite trailing '\0'
|
||||
memset(&(pgm->desc), 0, PGM_DESCLEN);
|
||||
for (i = 0; i < (PGM_DESCLEN-1) && buff[i]; i++)
|
||||
{
|
||||
pgm->desc[i] = (char)buff[i]; // TODO what about little/big endian???
|
||||
}
|
||||
if(pgm->desc && *pgm->desc)
|
||||
strcpy(cbuf, pgm->desc);
|
||||
|
||||
// Convert from wide chars and overlay over initial part of desc
|
||||
for (int i = 0; i < sizeof wbuf/sizeof*wbuf && wbuf[i]; i++)
|
||||
cbuf[i] = (char) wbuf[i]; // TODO what about little/big endian???
|
||||
pgm->desc = cache_string(cbuf);
|
||||
}
|
||||
#else
|
||||
if (usb_open_device(&(PDATA(pgm)->usb_handle), PICKIT2_VID, PICKIT2_PID) < 0)
|
||||
|
|
10
src/update.c
10
src/update.c
|
@ -306,11 +306,11 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
|
|||
return LIBAVRDUDE_SOFTFAIL;
|
||||
}
|
||||
|
||||
AVRMEM_ALIAS * alias_mem = avr_find_memalias(p, mem);
|
||||
char alias_mem_desc[AVR_DESCLEN + 1] = "";
|
||||
if(alias_mem) {
|
||||
strcat(alias_mem_desc, "/");
|
||||
strcat(alias_mem_desc, alias_mem->desc);
|
||||
AVRMEM_ALIAS *alias_mem = avr_find_memalias(p, mem);
|
||||
char *alias_mem_desc = cfg_malloc("do_op()", 2 + (alias_mem && alias_mem->desc? strlen(alias_mem->desc): 0));
|
||||
if(alias_mem && alias_mem->desc && *alias_mem->desc) {
|
||||
*alias_mem_desc = '/';
|
||||
strcpy(alias_mem_desc+1, alias_mem->desc);
|
||||
}
|
||||
|
||||
switch (upd->op) {
|
||||
|
|
Loading…
Reference in New Issue