2003-11-30 16:42:10 +00:00
|
|
|
/*
|
|
|
|
* avrdude - A Downloader/Uploader for AVR device programmers
|
2004-12-22 01:52:45 +00:00
|
|
|
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bsdhome.com>
|
2006-07-16 21:30:14 +00:00
|
|
|
* Copyright (C) 2006 Joerg Wunsch <j@uriah.heep.sax.de>
|
2003-11-30 16:42:10 +00:00
|
|
|
*
|
|
|
|
* 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
|
2012-11-20 14:03:50 +00:00
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2003-11-30 16:42:10 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* $Id$ */
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2022-01-10 13:27:08 +00:00
|
|
|
#include "ac_cfg.h"
|
2007-01-24 21:07:54 +00:00
|
|
|
#include "avrdude.h"
|
2014-05-19 10:01:59 +00:00
|
|
|
#include "libavrdude.h"
|
2003-11-30 16:42:10 +00:00
|
|
|
|
|
|
|
/***
|
|
|
|
*** Elementary functions dealing with OPCODE structures
|
|
|
|
***/
|
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
OPCODE *avr_new_opcode(void) {
|
|
|
|
return (OPCODE *) cfg_malloc("avr_new_opcode()", sizeof(OPCODE));
|
2003-11-30 16:42:10 +00:00
|
|
|
}
|
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
static OPCODE *avr_dup_opcode(const OPCODE *op) {
|
|
|
|
if(op == NULL) // Caller wants NULL if op == NULL
|
2011-12-29 16:51:44 +00:00
|
|
|
return NULL;
|
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
OPCODE *m = (OPCODE *) cfg_malloc("avr_dup_opcode()", sizeof(*m));
|
2011-12-29 16:51:44 +00:00
|
|
|
memcpy(m, op, sizeof(*m));
|
|
|
|
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
void avr_free_opcode(OPCODE *op) {
|
|
|
|
if(op)
|
|
|
|
free(op);
|
2012-01-17 20:56:37 +00:00
|
|
|
}
|
2003-11-30 16:42:10 +00:00
|
|
|
|
2022-07-26 23:12:57 +00:00
|
|
|
|
|
|
|
// returns position 0..31 of highest bit set or INT_MIN if no bit is set
|
|
|
|
int intlog2(unsigned int n) {
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if(!n)
|
|
|
|
return INT_MIN;
|
|
|
|
|
|
|
|
for(ret = 0; n >>= 1; ret++)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-30 16:42:10 +00:00
|
|
|
/*
|
|
|
|
* avr_set_bits()
|
|
|
|
*
|
|
|
|
* Set instruction bits in the specified command based on the opcode.
|
|
|
|
*/
|
2022-08-23 15:57:09 +00:00
|
|
|
int avr_set_bits(const OPCODE *op, unsigned char *cmd) {
|
2003-11-30 16:42:10 +00:00
|
|
|
int i, j, bit;
|
|
|
|
unsigned char mask;
|
|
|
|
|
|
|
|
for (i=0; i<32; i++) {
|
2022-04-28 23:37:28 +00:00
|
|
|
if (op->bit[i].type == AVR_CMDBIT_VALUE || op->bit[i].type == AVR_CMDBIT_IGNORE) {
|
2003-11-30 16:42:10 +00:00
|
|
|
j = 3 - i / 8;
|
|
|
|
bit = i % 8;
|
|
|
|
mask = 1 << bit;
|
2022-04-28 23:37:28 +00:00
|
|
|
if (op->bit[i].value && op->bit[i].type == AVR_CMDBIT_VALUE)
|
2003-11-30 16:42:10 +00:00
|
|
|
cmd[j] = cmd[j] | mask;
|
|
|
|
else
|
|
|
|
cmd[j] = cmd[j] & ~mask;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* avr_set_addr()
|
|
|
|
*
|
|
|
|
* Set address bits in the specified command based on the opcode, and
|
|
|
|
* the address.
|
|
|
|
*/
|
2022-08-23 15:57:09 +00:00
|
|
|
int avr_set_addr(const OPCODE *op, unsigned char *cmd, unsigned long addr) {
|
2003-11-30 16:42:10 +00:00
|
|
|
int i, j, bit;
|
|
|
|
unsigned long value;
|
|
|
|
unsigned char mask;
|
|
|
|
|
|
|
|
for (i=0; i<32; i++) {
|
|
|
|
if (op->bit[i].type == AVR_CMDBIT_ADDRESS) {
|
|
|
|
j = 3 - i / 8;
|
|
|
|
bit = i % 8;
|
|
|
|
mask = 1 << bit;
|
|
|
|
value = addr >> op->bit[i].bitno & 0x01;
|
|
|
|
if (value)
|
|
|
|
cmd[j] = cmd[j] | mask;
|
|
|
|
else
|
|
|
|
cmd[j] = cmd[j] & ~mask;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-07-26 23:12:57 +00:00
|
|
|
/*
|
|
|
|
* avr_set_addr_mem()
|
|
|
|
*
|
|
|
|
* Set address bits in the specified command based on the memory, opcode and
|
|
|
|
* address; addr must be a word address for flash or, for all other memories,
|
|
|
|
* a byte address; returns 0 on success and -1 on error (no memory or no
|
|
|
|
* opcode) or, if positive, bn+1 where bn is bit number of the highest
|
|
|
|
* necessary bit that the opcode does not provide.
|
|
|
|
*/
|
2022-08-23 15:57:09 +00:00
|
|
|
int avr_set_addr_mem(const AVRMEM *mem, int opnum, unsigned char *cmd, unsigned long addr) {
|
2022-07-26 23:12:57 +00:00
|
|
|
int ret, isflash, lo, hi, memsize, pagesize;
|
|
|
|
OPCODE *op;
|
|
|
|
|
|
|
|
if(!mem)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if(!(op = mem->op[opnum]))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
isflash = !strcmp(mem->desc, "flash"); // ISP parts have only one flash-like memory
|
|
|
|
memsize = mem->size >> isflash; // word addresses for flash
|
|
|
|
pagesize = mem->page_size >> isflash;
|
|
|
|
|
|
|
|
// compute range lo..hi of needed address bits
|
|
|
|
switch(opnum) {
|
|
|
|
case AVR_OP_READ:
|
|
|
|
case AVR_OP_WRITE:
|
|
|
|
case AVR_OP_READ_LO:
|
|
|
|
case AVR_OP_READ_HI:
|
|
|
|
case AVR_OP_WRITE_LO:
|
|
|
|
case AVR_OP_WRITE_HI:
|
|
|
|
lo = 0;
|
|
|
|
hi = intlog2(memsize-1); // memsize = 1 implies no addr bit is needed
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AVR_OP_LOADPAGE_LO:
|
|
|
|
case AVR_OP_LOADPAGE_HI:
|
|
|
|
lo = 0;
|
|
|
|
hi = intlog2(pagesize-1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AVR_OP_LOAD_EXT_ADDR:
|
|
|
|
lo = 16;
|
|
|
|
hi = intlog2(memsize-1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AVR_OP_WRITEPAGE:
|
|
|
|
lo = intlog2(pagesize);
|
|
|
|
hi = intlog2(memsize-1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AVR_OP_CHIP_ERASE:
|
|
|
|
case AVR_OP_PGM_ENABLE:
|
|
|
|
default:
|
|
|
|
lo = 0;
|
|
|
|
hi = -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Unless it's load extended address, ISP chips only deal with 16 bit addresses
|
|
|
|
if(opnum != AVR_OP_LOAD_EXT_ADDR && hi > 15)
|
|
|
|
hi = 15;
|
|
|
|
|
|
|
|
unsigned char avail[32];
|
|
|
|
memset(avail, 0, sizeof avail);
|
|
|
|
|
|
|
|
for(int i=0; i<32; i++) {
|
|
|
|
if(op->bit[i].type == AVR_CMDBIT_ADDRESS) {
|
|
|
|
int bitno, j, bit;
|
|
|
|
unsigned char mask;
|
|
|
|
|
|
|
|
bitno = op->bit[i].bitno & 31;
|
|
|
|
j = 3 - i / 8;
|
|
|
|
bit = i % 8;
|
|
|
|
mask = 1 << bit;
|
|
|
|
avail[bitno] = 1;
|
|
|
|
|
|
|
|
// 'a' bit with number outside bit range [lo, hi] is set to 0
|
|
|
|
if (bitno >= lo && bitno <= hi? (addr >> bitno) & 1: 0)
|
|
|
|
cmd[j] = cmd[j] | mask;
|
|
|
|
else
|
|
|
|
cmd[j] = cmd[j] & ~mask;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
if(lo >= 0 && hi < 32 && lo <= hi)
|
|
|
|
for(int bn=lo; bn <= hi; bn++)
|
|
|
|
if(!avail[bn]) // necessary bit bn misses in opcode
|
|
|
|
ret = bn+1;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-30 16:42:10 +00:00
|
|
|
/*
|
|
|
|
* avr_set_input()
|
|
|
|
*
|
|
|
|
* Set input data bits in the specified command based on the opcode,
|
|
|
|
* and the data byte.
|
|
|
|
*/
|
2022-08-23 15:57:09 +00:00
|
|
|
int avr_set_input(const OPCODE *op, unsigned char *cmd, unsigned char data) {
|
2003-11-30 16:42:10 +00:00
|
|
|
int i, j, bit;
|
|
|
|
unsigned char value;
|
|
|
|
unsigned char mask;
|
|
|
|
|
|
|
|
for (i=0; i<32; i++) {
|
|
|
|
if (op->bit[i].type == AVR_CMDBIT_INPUT) {
|
|
|
|
j = 3 - i / 8;
|
|
|
|
bit = i % 8;
|
|
|
|
mask = 1 << bit;
|
|
|
|
value = data >> op->bit[i].bitno & 0x01;
|
|
|
|
if (value)
|
|
|
|
cmd[j] = cmd[j] | mask;
|
|
|
|
else
|
|
|
|
cmd[j] = cmd[j] & ~mask;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* avr_get_output()
|
|
|
|
*
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
* Retrieve output data bits from the command results based on the
|
2003-11-30 16:42:10 +00:00
|
|
|
* opcode data.
|
|
|
|
*/
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
int avr_get_output(const OPCODE *op, const unsigned char *res, unsigned char *data) {
|
2003-11-30 16:42:10 +00:00
|
|
|
int i, j, bit;
|
|
|
|
unsigned char value;
|
|
|
|
unsigned char mask;
|
|
|
|
|
|
|
|
for (i=0; i<32; i++) {
|
|
|
|
if (op->bit[i].type == AVR_CMDBIT_OUTPUT) {
|
|
|
|
j = 3 - i / 8;
|
|
|
|
bit = i % 8;
|
|
|
|
mask = 1 << bit;
|
|
|
|
value = ((res[j] & mask) >> bit) & 0x01;
|
|
|
|
value = value << op->bit[i].bitno;
|
|
|
|
if (value)
|
|
|
|
*data = *data | value;
|
|
|
|
else
|
|
|
|
*data = *data & ~value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-12-03 15:52:38 +00:00
|
|
|
/*
|
|
|
|
* avr_get_output_index()
|
|
|
|
*
|
|
|
|
* Calculate the byte number of the output data based on the
|
|
|
|
* opcode data.
|
|
|
|
*/
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
int avr_get_output_index(const OPCODE *op) {
|
2012-12-03 15:52:38 +00:00
|
|
|
int i, j;
|
|
|
|
|
|
|
|
for (i=0; i<32; i++) {
|
|
|
|
if (op->bit[i].type == AVR_CMDBIT_OUTPUT) {
|
|
|
|
j = 3 - i / 8;
|
|
|
|
return j;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-24 22:43:46 +00:00
|
|
|
static char * avr_op_str(int op)
|
2003-11-30 16:42:10 +00:00
|
|
|
{
|
|
|
|
switch (op) {
|
|
|
|
case AVR_OP_READ : return "READ"; break;
|
|
|
|
case AVR_OP_WRITE : return "WRITE"; break;
|
|
|
|
case AVR_OP_READ_LO : return "READ_LO"; break;
|
|
|
|
case AVR_OP_READ_HI : return "READ_HI"; break;
|
|
|
|
case AVR_OP_WRITE_LO : return "WRITE_LO"; break;
|
|
|
|
case AVR_OP_WRITE_HI : return "WRITE_HI"; break;
|
|
|
|
case AVR_OP_LOADPAGE_LO : return "LOADPAGE_LO"; break;
|
|
|
|
case AVR_OP_LOADPAGE_HI : return "LOADPAGE_HI"; break;
|
2006-05-23 22:27:43 +00:00
|
|
|
case AVR_OP_LOAD_EXT_ADDR : return "LOAD_EXT_ADDR"; break;
|
2003-11-30 16:42:10 +00:00
|
|
|
case AVR_OP_WRITEPAGE : return "WRITEPAGE"; break;
|
|
|
|
case AVR_OP_CHIP_ERASE : return "CHIP_ERASE"; break;
|
|
|
|
case AVR_OP_PGM_ENABLE : return "PGM_ENABLE"; break;
|
|
|
|
default : return "<unknown opcode>"; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-24 22:43:46 +00:00
|
|
|
static char * bittype(int type)
|
2003-11-30 16:42:10 +00:00
|
|
|
{
|
|
|
|
switch (type) {
|
|
|
|
case AVR_CMDBIT_IGNORE : return "IGNORE"; break;
|
|
|
|
case AVR_CMDBIT_VALUE : return "VALUE"; break;
|
|
|
|
case AVR_CMDBIT_ADDRESS : return "ADDRESS"; break;
|
|
|
|
case AVR_CMDBIT_INPUT : return "INPUT"; break;
|
|
|
|
case AVR_CMDBIT_OUTPUT : return "OUTPUT"; break;
|
|
|
|
default : return "<unknown bit type>"; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***
|
|
|
|
*** Elementary functions dealing with AVRMEM structures
|
|
|
|
***/
|
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
AVRMEM *avr_new_memtype(void) {
|
|
|
|
AVRMEM *m = (AVRMEM *) cfg_malloc("avr_new_memtype()", sizeof(*m));
|
|
|
|
m->desc = cache_string("");
|
2020-09-10 21:37:34 +00:00
|
|
|
m->page_size = 1; // ensure not 0
|
2003-11-30 16:42:10 +00:00
|
|
|
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
AVRMEM_ALIAS *avr_new_memalias(void) {
|
|
|
|
AVRMEM_ALIAS *m = (AVRMEM_ALIAS *) cfg_malloc("avr_new_memalias()", sizeof*m);
|
|
|
|
m->desc = cache_string("");
|
Alias keyword (#868)
Implementation for an "alias" keyword.
By now, only applied inside memory descriptions.
* Make "mem_alias" a separate nonterminal.
The previous implementation attempt caused a syntax error in
yacc code, and separating mem_alias on the same level as
mem_spec appears to be the cleaner solution anyway.
* Maintain real memory aliases.
Instead of duplicating the aliased memory with a new name, maintain a
second list of memory aliases (per device) that contains a pointer to
the memory area it is aliased to. That way, a memory name can be
clearly distinguished between the canonical one and any aliases.
* Check p->mem_alias != NULL before touching it
* Add avr_find_memalias()
This takes a memory region as input, and searches whether an
alias can be found for it.
* We need to add a list structure for the mem_alias list, always.
By that means, mem_alias won't ever be NULL, so no need to check
later.
Also, in avr_dup_part(), duplicate the alias list.
* In a memory alias, actually remember the current name.
* In avr_dup_part(), adjust pointers of aliased memories
While walking the list of memories, for each entry, see if there is an
alias pointing to it. If so, allocate a duplicated one, and fix its
aliased_mem pointer to point to the duplicated memory region instead
of the original one.
* Add avr_locate_mem_noalias()
When looking whether any memory region has already been defined for
the current part while parsing the config file, only non-aliased names
must be considered. Otherwise, a newly defined alias would kick out
the memory definition it is being aliased to.
* When defining a mem_alias, drop any existing one of that name.
* Actually use avr_find_memalias() to find aliases
* Add declaration for avr_find_memalias()
* When defining a memory, also search for an existing alias
If the newly defined name has the same as an existing alias, the alias
can be removed.
Note that we do explicitly *not* remove any memory by the same name of
a later defined alias, as this might invalidate another alias'es
pointer. If someone defines that, the alias name just won't ever be
found by avr_locate_mem().
2022-02-10 19:39:19 +00:00
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2003-11-30 16:42:10 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Allocate and initialize memory buffers for each of the device's
|
|
|
|
* defined memory regions.
|
|
|
|
*/
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
int avr_initmem(const AVRPART *p) {
|
|
|
|
if(p == NULL || p->mem == NULL)
|
|
|
|
return -1;
|
2003-11-30 16:42:10 +00:00
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
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);
|
2003-11-30 16:42:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
AVRMEM *avr_dup_mem(const AVRMEM *m) {
|
|
|
|
AVRMEM *n = avr_new_memtype();
|
2003-11-30 16:42:10 +00:00
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
if(m) {
|
|
|
|
*n = *m;
|
2003-11-30 16:42:10 +00:00
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
if(m->buf) {
|
|
|
|
n->buf = (unsigned char *) cfg_malloc("avr_dup_mem()", n->size);
|
|
|
|
memcpy(n->buf, m->buf, n->size);
|
2011-12-29 16:51:44 +00:00
|
|
|
}
|
2011-09-14 21:49:42 +00:00
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
if(m->tags) {
|
|
|
|
n->tags = (unsigned char *) cfg_malloc("avr_dup_mem()", n->size);
|
|
|
|
memcpy(n->tags, m->tags, n->size);
|
2011-12-29 16:51:44 +00:00
|
|
|
}
|
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
for(int i = 0; i < AVR_OP_MAX; i++)
|
|
|
|
n->op[i] = avr_dup_opcode(n->op[i]);
|
2011-09-14 21:49:42 +00:00
|
|
|
}
|
2003-11-30 16:42:10 +00:00
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
AVRMEM_ALIAS *avr_dup_memalias(const AVRMEM_ALIAS *m) {
|
|
|
|
AVRMEM_ALIAS *n = avr_new_memalias();
|
Alias keyword (#868)
Implementation for an "alias" keyword.
By now, only applied inside memory descriptions.
* Make "mem_alias" a separate nonterminal.
The previous implementation attempt caused a syntax error in
yacc code, and separating mem_alias on the same level as
mem_spec appears to be the cleaner solution anyway.
* Maintain real memory aliases.
Instead of duplicating the aliased memory with a new name, maintain a
second list of memory aliases (per device) that contains a pointer to
the memory area it is aliased to. That way, a memory name can be
clearly distinguished between the canonical one and any aliases.
* Check p->mem_alias != NULL before touching it
* Add avr_find_memalias()
This takes a memory region as input, and searches whether an
alias can be found for it.
* We need to add a list structure for the mem_alias list, always.
By that means, mem_alias won't ever be NULL, so no need to check
later.
Also, in avr_dup_part(), duplicate the alias list.
* In a memory alias, actually remember the current name.
* In avr_dup_part(), adjust pointers of aliased memories
While walking the list of memories, for each entry, see if there is an
alias pointing to it. If so, allocate a duplicated one, and fix its
aliased_mem pointer to point to the duplicated memory region instead
of the original one.
* Add avr_locate_mem_noalias()
When looking whether any memory region has already been defined for
the current part while parsing the config file, only non-aliased names
must be considered. Otherwise, a newly defined alias would kick out
the memory definition it is being aliased to.
* When defining a mem_alias, drop any existing one of that name.
* Actually use avr_find_memalias() to find aliases
* Add declaration for avr_find_memalias()
* When defining a memory, also search for an existing alias
If the newly defined name has the same as an existing alias, the alias
can be removed.
Note that we do explicitly *not* remove any memory by the same name of
a later defined alias, as this might invalidate another alias'es
pointer. If someone defines that, the alias name just won't ever be
found by avr_locate_mem().
2022-02-10 19:39:19 +00:00
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
if(m)
|
|
|
|
*n = *m;
|
Alias keyword (#868)
Implementation for an "alias" keyword.
By now, only applied inside memory descriptions.
* Make "mem_alias" a separate nonterminal.
The previous implementation attempt caused a syntax error in
yacc code, and separating mem_alias on the same level as
mem_spec appears to be the cleaner solution anyway.
* Maintain real memory aliases.
Instead of duplicating the aliased memory with a new name, maintain a
second list of memory aliases (per device) that contains a pointer to
the memory area it is aliased to. That way, a memory name can be
clearly distinguished between the canonical one and any aliases.
* Check p->mem_alias != NULL before touching it
* Add avr_find_memalias()
This takes a memory region as input, and searches whether an
alias can be found for it.
* We need to add a list structure for the mem_alias list, always.
By that means, mem_alias won't ever be NULL, so no need to check
later.
Also, in avr_dup_part(), duplicate the alias list.
* In a memory alias, actually remember the current name.
* In avr_dup_part(), adjust pointers of aliased memories
While walking the list of memories, for each entry, see if there is an
alias pointing to it. If so, allocate a duplicated one, and fix its
aliased_mem pointer to point to the duplicated memory region instead
of the original one.
* Add avr_locate_mem_noalias()
When looking whether any memory region has already been defined for
the current part while parsing the config file, only non-aliased names
must be considered. Otherwise, a newly defined alias would kick out
the memory definition it is being aliased to.
* When defining a mem_alias, drop any existing one of that name.
* Actually use avr_find_memalias() to find aliases
* Add declaration for avr_find_memalias()
* When defining a memory, also search for an existing alias
If the newly defined name has the same as an existing alias, the alias
can be removed.
Note that we do explicitly *not* remove any memory by the same name of
a later defined alias, as this might invalidate another alias'es
pointer. If someone defines that, the alias name just won't ever be
found by avr_locate_mem().
2022-02-10 19:39:19 +00:00
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
void avr_free_mem(AVRMEM * m) {
|
|
|
|
if(m == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
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;
|
2012-01-17 20:56:37 +00:00
|
|
|
}
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
}
|
|
|
|
free(m);
|
2012-01-17 20:56:37 +00:00
|
|
|
}
|
2003-11-30 16:42:10 +00:00
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
void avr_free_memalias(AVRMEM_ALIAS *m) {
|
|
|
|
if(m)
|
|
|
|
free(m);
|
Alias keyword (#868)
Implementation for an "alias" keyword.
By now, only applied inside memory descriptions.
* Make "mem_alias" a separate nonterminal.
The previous implementation attempt caused a syntax error in
yacc code, and separating mem_alias on the same level as
mem_spec appears to be the cleaner solution anyway.
* Maintain real memory aliases.
Instead of duplicating the aliased memory with a new name, maintain a
second list of memory aliases (per device) that contains a pointer to
the memory area it is aliased to. That way, a memory name can be
clearly distinguished between the canonical one and any aliases.
* Check p->mem_alias != NULL before touching it
* Add avr_find_memalias()
This takes a memory region as input, and searches whether an
alias can be found for it.
* We need to add a list structure for the mem_alias list, always.
By that means, mem_alias won't ever be NULL, so no need to check
later.
Also, in avr_dup_part(), duplicate the alias list.
* In a memory alias, actually remember the current name.
* In avr_dup_part(), adjust pointers of aliased memories
While walking the list of memories, for each entry, see if there is an
alias pointing to it. If so, allocate a duplicated one, and fix its
aliased_mem pointer to point to the duplicated memory region instead
of the original one.
* Add avr_locate_mem_noalias()
When looking whether any memory region has already been defined for
the current part while parsing the config file, only non-aliased names
must be considered. Otherwise, a newly defined alias would kick out
the memory definition it is being aliased to.
* When defining a mem_alias, drop any existing one of that name.
* Actually use avr_find_memalias() to find aliases
* Add declaration for avr_find_memalias()
* When defining a memory, also search for an existing alias
If the newly defined name has the same as an existing alias, the alias
can be removed.
Note that we do explicitly *not* remove any memory by the same name of
a later defined alias, as this might invalidate another alias'es
pointer. If someone defines that, the alias name just won't ever be
found by avr_locate_mem().
2022-02-10 19:39:19 +00:00
|
|
|
}
|
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
AVRMEM_ALIAS *avr_locate_memalias(const AVRPART *p, const char *desc) {
|
Alias keyword (#868)
Implementation for an "alias" keyword.
By now, only applied inside memory descriptions.
* Make "mem_alias" a separate nonterminal.
The previous implementation attempt caused a syntax error in
yacc code, and separating mem_alias on the same level as
mem_spec appears to be the cleaner solution anyway.
* Maintain real memory aliases.
Instead of duplicating the aliased memory with a new name, maintain a
second list of memory aliases (per device) that contains a pointer to
the memory area it is aliased to. That way, a memory name can be
clearly distinguished between the canonical one and any aliases.
* Check p->mem_alias != NULL before touching it
* Add avr_find_memalias()
This takes a memory region as input, and searches whether an
alias can be found for it.
* We need to add a list structure for the mem_alias list, always.
By that means, mem_alias won't ever be NULL, so no need to check
later.
Also, in avr_dup_part(), duplicate the alias list.
* In a memory alias, actually remember the current name.
* In avr_dup_part(), adjust pointers of aliased memories
While walking the list of memories, for each entry, see if there is an
alias pointing to it. If so, allocate a duplicated one, and fix its
aliased_mem pointer to point to the duplicated memory region instead
of the original one.
* Add avr_locate_mem_noalias()
When looking whether any memory region has already been defined for
the current part while parsing the config file, only non-aliased names
must be considered. Otherwise, a newly defined alias would kick out
the memory definition it is being aliased to.
* When defining a mem_alias, drop any existing one of that name.
* Actually use avr_find_memalias() to find aliases
* Add declaration for avr_find_memalias()
* When defining a memory, also search for an existing alias
If the newly defined name has the same as an existing alias, the alias
can be removed.
Note that we do explicitly *not* remove any memory by the same name of
a later defined alias, as this might invalidate another alias'es
pointer. If someone defines that, the alias name just won't ever be
found by avr_locate_mem().
2022-02-10 19:39:19 +00:00
|
|
|
AVRMEM_ALIAS * m, * match;
|
|
|
|
LNODEID ln;
|
2022-08-13 19:51:12 +00:00
|
|
|
int matches, exact;
|
Alias keyword (#868)
Implementation for an "alias" keyword.
By now, only applied inside memory descriptions.
* Make "mem_alias" a separate nonterminal.
The previous implementation attempt caused a syntax error in
yacc code, and separating mem_alias on the same level as
mem_spec appears to be the cleaner solution anyway.
* Maintain real memory aliases.
Instead of duplicating the aliased memory with a new name, maintain a
second list of memory aliases (per device) that contains a pointer to
the memory area it is aliased to. That way, a memory name can be
clearly distinguished between the canonical one and any aliases.
* Check p->mem_alias != NULL before touching it
* Add avr_find_memalias()
This takes a memory region as input, and searches whether an
alias can be found for it.
* We need to add a list structure for the mem_alias list, always.
By that means, mem_alias won't ever be NULL, so no need to check
later.
Also, in avr_dup_part(), duplicate the alias list.
* In a memory alias, actually remember the current name.
* In avr_dup_part(), adjust pointers of aliased memories
While walking the list of memories, for each entry, see if there is an
alias pointing to it. If so, allocate a duplicated one, and fix its
aliased_mem pointer to point to the duplicated memory region instead
of the original one.
* Add avr_locate_mem_noalias()
When looking whether any memory region has already been defined for
the current part while parsing the config file, only non-aliased names
must be considered. Otherwise, a newly defined alias would kick out
the memory definition it is being aliased to.
* When defining a mem_alias, drop any existing one of that name.
* Actually use avr_find_memalias() to find aliases
* Add declaration for avr_find_memalias()
* When defining a memory, also search for an existing alias
If the newly defined name has the same as an existing alias, the alias
can be removed.
Note that we do explicitly *not* remove any memory by the same name of
a later defined alias, as this might invalidate another alias'es
pointer. If someone defines that, the alias name just won't ever be
found by avr_locate_mem().
2022-02-10 19:39:19 +00:00
|
|
|
int l;
|
|
|
|
|
2022-07-07 17:32:19 +00:00
|
|
|
if(!p || !desc || !p->mem_alias)
|
|
|
|
return NULL;
|
|
|
|
|
Alias keyword (#868)
Implementation for an "alias" keyword.
By now, only applied inside memory descriptions.
* Make "mem_alias" a separate nonterminal.
The previous implementation attempt caused a syntax error in
yacc code, and separating mem_alias on the same level as
mem_spec appears to be the cleaner solution anyway.
* Maintain real memory aliases.
Instead of duplicating the aliased memory with a new name, maintain a
second list of memory aliases (per device) that contains a pointer to
the memory area it is aliased to. That way, a memory name can be
clearly distinguished between the canonical one and any aliases.
* Check p->mem_alias != NULL before touching it
* Add avr_find_memalias()
This takes a memory region as input, and searches whether an
alias can be found for it.
* We need to add a list structure for the mem_alias list, always.
By that means, mem_alias won't ever be NULL, so no need to check
later.
Also, in avr_dup_part(), duplicate the alias list.
* In a memory alias, actually remember the current name.
* In avr_dup_part(), adjust pointers of aliased memories
While walking the list of memories, for each entry, see if there is an
alias pointing to it. If so, allocate a duplicated one, and fix its
aliased_mem pointer to point to the duplicated memory region instead
of the original one.
* Add avr_locate_mem_noalias()
When looking whether any memory region has already been defined for
the current part while parsing the config file, only non-aliased names
must be considered. Otherwise, a newly defined alias would kick out
the memory definition it is being aliased to.
* When defining a mem_alias, drop any existing one of that name.
* Actually use avr_find_memalias() to find aliases
* Add declaration for avr_find_memalias()
* When defining a memory, also search for an existing alias
If the newly defined name has the same as an existing alias, the alias
can be removed.
Note that we do explicitly *not* remove any memory by the same name of
a later defined alias, as this might invalidate another alias'es
pointer. If someone defines that, the alias name just won't ever be
found by avr_locate_mem().
2022-02-10 19:39:19 +00:00
|
|
|
l = strlen(desc);
|
2022-08-13 19:51:12 +00:00
|
|
|
matches = exact = 0;
|
Alias keyword (#868)
Implementation for an "alias" keyword.
By now, only applied inside memory descriptions.
* Make "mem_alias" a separate nonterminal.
The previous implementation attempt caused a syntax error in
yacc code, and separating mem_alias on the same level as
mem_spec appears to be the cleaner solution anyway.
* Maintain real memory aliases.
Instead of duplicating the aliased memory with a new name, maintain a
second list of memory aliases (per device) that contains a pointer to
the memory area it is aliased to. That way, a memory name can be
clearly distinguished between the canonical one and any aliases.
* Check p->mem_alias != NULL before touching it
* Add avr_find_memalias()
This takes a memory region as input, and searches whether an
alias can be found for it.
* We need to add a list structure for the mem_alias list, always.
By that means, mem_alias won't ever be NULL, so no need to check
later.
Also, in avr_dup_part(), duplicate the alias list.
* In a memory alias, actually remember the current name.
* In avr_dup_part(), adjust pointers of aliased memories
While walking the list of memories, for each entry, see if there is an
alias pointing to it. If so, allocate a duplicated one, and fix its
aliased_mem pointer to point to the duplicated memory region instead
of the original one.
* Add avr_locate_mem_noalias()
When looking whether any memory region has already been defined for
the current part while parsing the config file, only non-aliased names
must be considered. Otherwise, a newly defined alias would kick out
the memory definition it is being aliased to.
* When defining a mem_alias, drop any existing one of that name.
* Actually use avr_find_memalias() to find aliases
* Add declaration for avr_find_memalias()
* When defining a memory, also search for an existing alias
If the newly defined name has the same as an existing alias, the alias
can be removed.
Note that we do explicitly *not* remove any memory by the same name of
a later defined alias, as this might invalidate another alias'es
pointer. If someone defines that, the alias name just won't ever be
found by avr_locate_mem().
2022-02-10 19:39:19 +00:00
|
|
|
match = NULL;
|
|
|
|
for (ln=lfirst(p->mem_alias); ln; ln=lnext(ln)) {
|
|
|
|
m = ldata(ln);
|
2022-08-13 19:51:12 +00:00
|
|
|
if (strncmp(m->desc, desc, l) == 0) { // Partial initial match
|
Alias keyword (#868)
Implementation for an "alias" keyword.
By now, only applied inside memory descriptions.
* Make "mem_alias" a separate nonterminal.
The previous implementation attempt caused a syntax error in
yacc code, and separating mem_alias on the same level as
mem_spec appears to be the cleaner solution anyway.
* Maintain real memory aliases.
Instead of duplicating the aliased memory with a new name, maintain a
second list of memory aliases (per device) that contains a pointer to
the memory area it is aliased to. That way, a memory name can be
clearly distinguished between the canonical one and any aliases.
* Check p->mem_alias != NULL before touching it
* Add avr_find_memalias()
This takes a memory region as input, and searches whether an
alias can be found for it.
* We need to add a list structure for the mem_alias list, always.
By that means, mem_alias won't ever be NULL, so no need to check
later.
Also, in avr_dup_part(), duplicate the alias list.
* In a memory alias, actually remember the current name.
* In avr_dup_part(), adjust pointers of aliased memories
While walking the list of memories, for each entry, see if there is an
alias pointing to it. If so, allocate a duplicated one, and fix its
aliased_mem pointer to point to the duplicated memory region instead
of the original one.
* Add avr_locate_mem_noalias()
When looking whether any memory region has already been defined for
the current part while parsing the config file, only non-aliased names
must be considered. Otherwise, a newly defined alias would kick out
the memory definition it is being aliased to.
* When defining a mem_alias, drop any existing one of that name.
* Actually use avr_find_memalias() to find aliases
* Add declaration for avr_find_memalias()
* When defining a memory, also search for an existing alias
If the newly defined name has the same as an existing alias, the alias
can be removed.
Note that we do explicitly *not* remove any memory by the same name of
a later defined alias, as this might invalidate another alias'es
pointer. If someone defines that, the alias name just won't ever be
found by avr_locate_mem().
2022-02-10 19:39:19 +00:00
|
|
|
match = m;
|
|
|
|
matches++;
|
2022-08-13 19:51:12 +00:00
|
|
|
if(m->desc[l] == 0) // Exact match between arg and memory
|
|
|
|
exact++;
|
Alias keyword (#868)
Implementation for an "alias" keyword.
By now, only applied inside memory descriptions.
* Make "mem_alias" a separate nonterminal.
The previous implementation attempt caused a syntax error in
yacc code, and separating mem_alias on the same level as
mem_spec appears to be the cleaner solution anyway.
* Maintain real memory aliases.
Instead of duplicating the aliased memory with a new name, maintain a
second list of memory aliases (per device) that contains a pointer to
the memory area it is aliased to. That way, a memory name can be
clearly distinguished between the canonical one and any aliases.
* Check p->mem_alias != NULL before touching it
* Add avr_find_memalias()
This takes a memory region as input, and searches whether an
alias can be found for it.
* We need to add a list structure for the mem_alias list, always.
By that means, mem_alias won't ever be NULL, so no need to check
later.
Also, in avr_dup_part(), duplicate the alias list.
* In a memory alias, actually remember the current name.
* In avr_dup_part(), adjust pointers of aliased memories
While walking the list of memories, for each entry, see if there is an
alias pointing to it. If so, allocate a duplicated one, and fix its
aliased_mem pointer to point to the duplicated memory region instead
of the original one.
* Add avr_locate_mem_noalias()
When looking whether any memory region has already been defined for
the current part while parsing the config file, only non-aliased names
must be considered. Otherwise, a newly defined alias would kick out
the memory definition it is being aliased to.
* When defining a mem_alias, drop any existing one of that name.
* Actually use avr_find_memalias() to find aliases
* Add declaration for avr_find_memalias()
* When defining a memory, also search for an existing alias
If the newly defined name has the same as an existing alias, the alias
can be removed.
Note that we do explicitly *not* remove any memory by the same name of
a later defined alias, as this might invalidate another alias'es
pointer. If someone defines that, the alias name just won't ever be
found by avr_locate_mem().
2022-02-10 19:39:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-13 19:51:12 +00:00
|
|
|
return exact == 1 || matches == 1? match: NULL;
|
Alias keyword (#868)
Implementation for an "alias" keyword.
By now, only applied inside memory descriptions.
* Make "mem_alias" a separate nonterminal.
The previous implementation attempt caused a syntax error in
yacc code, and separating mem_alias on the same level as
mem_spec appears to be the cleaner solution anyway.
* Maintain real memory aliases.
Instead of duplicating the aliased memory with a new name, maintain a
second list of memory aliases (per device) that contains a pointer to
the memory area it is aliased to. That way, a memory name can be
clearly distinguished between the canonical one and any aliases.
* Check p->mem_alias != NULL before touching it
* Add avr_find_memalias()
This takes a memory region as input, and searches whether an
alias can be found for it.
* We need to add a list structure for the mem_alias list, always.
By that means, mem_alias won't ever be NULL, so no need to check
later.
Also, in avr_dup_part(), duplicate the alias list.
* In a memory alias, actually remember the current name.
* In avr_dup_part(), adjust pointers of aliased memories
While walking the list of memories, for each entry, see if there is an
alias pointing to it. If so, allocate a duplicated one, and fix its
aliased_mem pointer to point to the duplicated memory region instead
of the original one.
* Add avr_locate_mem_noalias()
When looking whether any memory region has already been defined for
the current part while parsing the config file, only non-aliased names
must be considered. Otherwise, a newly defined alias would kick out
the memory definition it is being aliased to.
* When defining a mem_alias, drop any existing one of that name.
* Actually use avr_find_memalias() to find aliases
* Add declaration for avr_find_memalias()
* When defining a memory, also search for an existing alias
If the newly defined name has the same as an existing alias, the alias
can be removed.
Note that we do explicitly *not* remove any memory by the same name of
a later defined alias, as this might invalidate another alias'es
pointer. If someone defines that, the alias name just won't ever be
found by avr_locate_mem().
2022-02-10 19:39:19 +00:00
|
|
|
}
|
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
AVRMEM *avr_locate_mem_noalias(const AVRPART *p, const char *desc) {
|
Alias keyword (#868)
Implementation for an "alias" keyword.
By now, only applied inside memory descriptions.
* Make "mem_alias" a separate nonterminal.
The previous implementation attempt caused a syntax error in
yacc code, and separating mem_alias on the same level as
mem_spec appears to be the cleaner solution anyway.
* Maintain real memory aliases.
Instead of duplicating the aliased memory with a new name, maintain a
second list of memory aliases (per device) that contains a pointer to
the memory area it is aliased to. That way, a memory name can be
clearly distinguished between the canonical one and any aliases.
* Check p->mem_alias != NULL before touching it
* Add avr_find_memalias()
This takes a memory region as input, and searches whether an
alias can be found for it.
* We need to add a list structure for the mem_alias list, always.
By that means, mem_alias won't ever be NULL, so no need to check
later.
Also, in avr_dup_part(), duplicate the alias list.
* In a memory alias, actually remember the current name.
* In avr_dup_part(), adjust pointers of aliased memories
While walking the list of memories, for each entry, see if there is an
alias pointing to it. If so, allocate a duplicated one, and fix its
aliased_mem pointer to point to the duplicated memory region instead
of the original one.
* Add avr_locate_mem_noalias()
When looking whether any memory region has already been defined for
the current part while parsing the config file, only non-aliased names
must be considered. Otherwise, a newly defined alias would kick out
the memory definition it is being aliased to.
* When defining a mem_alias, drop any existing one of that name.
* Actually use avr_find_memalias() to find aliases
* Add declaration for avr_find_memalias()
* When defining a memory, also search for an existing alias
If the newly defined name has the same as an existing alias, the alias
can be removed.
Note that we do explicitly *not* remove any memory by the same name of
a later defined alias, as this might invalidate another alias'es
pointer. If someone defines that, the alias name just won't ever be
found by avr_locate_mem().
2022-02-10 19:39:19 +00:00
|
|
|
AVRMEM * m, * match;
|
|
|
|
LNODEID ln;
|
2022-08-13 19:51:12 +00:00
|
|
|
int matches, exact;
|
Alias keyword (#868)
Implementation for an "alias" keyword.
By now, only applied inside memory descriptions.
* Make "mem_alias" a separate nonterminal.
The previous implementation attempt caused a syntax error in
yacc code, and separating mem_alias on the same level as
mem_spec appears to be the cleaner solution anyway.
* Maintain real memory aliases.
Instead of duplicating the aliased memory with a new name, maintain a
second list of memory aliases (per device) that contains a pointer to
the memory area it is aliased to. That way, a memory name can be
clearly distinguished between the canonical one and any aliases.
* Check p->mem_alias != NULL before touching it
* Add avr_find_memalias()
This takes a memory region as input, and searches whether an
alias can be found for it.
* We need to add a list structure for the mem_alias list, always.
By that means, mem_alias won't ever be NULL, so no need to check
later.
Also, in avr_dup_part(), duplicate the alias list.
* In a memory alias, actually remember the current name.
* In avr_dup_part(), adjust pointers of aliased memories
While walking the list of memories, for each entry, see if there is an
alias pointing to it. If so, allocate a duplicated one, and fix its
aliased_mem pointer to point to the duplicated memory region instead
of the original one.
* Add avr_locate_mem_noalias()
When looking whether any memory region has already been defined for
the current part while parsing the config file, only non-aliased names
must be considered. Otherwise, a newly defined alias would kick out
the memory definition it is being aliased to.
* When defining a mem_alias, drop any existing one of that name.
* Actually use avr_find_memalias() to find aliases
* Add declaration for avr_find_memalias()
* When defining a memory, also search for an existing alias
If the newly defined name has the same as an existing alias, the alias
can be removed.
Note that we do explicitly *not* remove any memory by the same name of
a later defined alias, as this might invalidate another alias'es
pointer. If someone defines that, the alias name just won't ever be
found by avr_locate_mem().
2022-02-10 19:39:19 +00:00
|
|
|
int l;
|
|
|
|
|
2022-07-07 17:32:19 +00:00
|
|
|
if(!p || !desc || !p->mem)
|
|
|
|
return NULL;
|
|
|
|
|
Alias keyword (#868)
Implementation for an "alias" keyword.
By now, only applied inside memory descriptions.
* Make "mem_alias" a separate nonterminal.
The previous implementation attempt caused a syntax error in
yacc code, and separating mem_alias on the same level as
mem_spec appears to be the cleaner solution anyway.
* Maintain real memory aliases.
Instead of duplicating the aliased memory with a new name, maintain a
second list of memory aliases (per device) that contains a pointer to
the memory area it is aliased to. That way, a memory name can be
clearly distinguished between the canonical one and any aliases.
* Check p->mem_alias != NULL before touching it
* Add avr_find_memalias()
This takes a memory region as input, and searches whether an
alias can be found for it.
* We need to add a list structure for the mem_alias list, always.
By that means, mem_alias won't ever be NULL, so no need to check
later.
Also, in avr_dup_part(), duplicate the alias list.
* In a memory alias, actually remember the current name.
* In avr_dup_part(), adjust pointers of aliased memories
While walking the list of memories, for each entry, see if there is an
alias pointing to it. If so, allocate a duplicated one, and fix its
aliased_mem pointer to point to the duplicated memory region instead
of the original one.
* Add avr_locate_mem_noalias()
When looking whether any memory region has already been defined for
the current part while parsing the config file, only non-aliased names
must be considered. Otherwise, a newly defined alias would kick out
the memory definition it is being aliased to.
* When defining a mem_alias, drop any existing one of that name.
* Actually use avr_find_memalias() to find aliases
* Add declaration for avr_find_memalias()
* When defining a memory, also search for an existing alias
If the newly defined name has the same as an existing alias, the alias
can be removed.
Note that we do explicitly *not* remove any memory by the same name of
a later defined alias, as this might invalidate another alias'es
pointer. If someone defines that, the alias name just won't ever be
found by avr_locate_mem().
2022-02-10 19:39:19 +00:00
|
|
|
l = strlen(desc);
|
2022-08-13 19:51:12 +00:00
|
|
|
matches = exact = 0;
|
Alias keyword (#868)
Implementation for an "alias" keyword.
By now, only applied inside memory descriptions.
* Make "mem_alias" a separate nonterminal.
The previous implementation attempt caused a syntax error in
yacc code, and separating mem_alias on the same level as
mem_spec appears to be the cleaner solution anyway.
* Maintain real memory aliases.
Instead of duplicating the aliased memory with a new name, maintain a
second list of memory aliases (per device) that contains a pointer to
the memory area it is aliased to. That way, a memory name can be
clearly distinguished between the canonical one and any aliases.
* Check p->mem_alias != NULL before touching it
* Add avr_find_memalias()
This takes a memory region as input, and searches whether an
alias can be found for it.
* We need to add a list structure for the mem_alias list, always.
By that means, mem_alias won't ever be NULL, so no need to check
later.
Also, in avr_dup_part(), duplicate the alias list.
* In a memory alias, actually remember the current name.
* In avr_dup_part(), adjust pointers of aliased memories
While walking the list of memories, for each entry, see if there is an
alias pointing to it. If so, allocate a duplicated one, and fix its
aliased_mem pointer to point to the duplicated memory region instead
of the original one.
* Add avr_locate_mem_noalias()
When looking whether any memory region has already been defined for
the current part while parsing the config file, only non-aliased names
must be considered. Otherwise, a newly defined alias would kick out
the memory definition it is being aliased to.
* When defining a mem_alias, drop any existing one of that name.
* Actually use avr_find_memalias() to find aliases
* Add declaration for avr_find_memalias()
* When defining a memory, also search for an existing alias
If the newly defined name has the same as an existing alias, the alias
can be removed.
Note that we do explicitly *not* remove any memory by the same name of
a later defined alias, as this might invalidate another alias'es
pointer. If someone defines that, the alias name just won't ever be
found by avr_locate_mem().
2022-02-10 19:39:19 +00:00
|
|
|
match = NULL;
|
|
|
|
for (ln=lfirst(p->mem); ln; ln=lnext(ln)) {
|
|
|
|
m = ldata(ln);
|
2022-08-13 19:51:12 +00:00
|
|
|
if (strncmp(m->desc, desc, l) == 0) { // Partial initial match
|
Alias keyword (#868)
Implementation for an "alias" keyword.
By now, only applied inside memory descriptions.
* Make "mem_alias" a separate nonterminal.
The previous implementation attempt caused a syntax error in
yacc code, and separating mem_alias on the same level as
mem_spec appears to be the cleaner solution anyway.
* Maintain real memory aliases.
Instead of duplicating the aliased memory with a new name, maintain a
second list of memory aliases (per device) that contains a pointer to
the memory area it is aliased to. That way, a memory name can be
clearly distinguished between the canonical one and any aliases.
* Check p->mem_alias != NULL before touching it
* Add avr_find_memalias()
This takes a memory region as input, and searches whether an
alias can be found for it.
* We need to add a list structure for the mem_alias list, always.
By that means, mem_alias won't ever be NULL, so no need to check
later.
Also, in avr_dup_part(), duplicate the alias list.
* In a memory alias, actually remember the current name.
* In avr_dup_part(), adjust pointers of aliased memories
While walking the list of memories, for each entry, see if there is an
alias pointing to it. If so, allocate a duplicated one, and fix its
aliased_mem pointer to point to the duplicated memory region instead
of the original one.
* Add avr_locate_mem_noalias()
When looking whether any memory region has already been defined for
the current part while parsing the config file, only non-aliased names
must be considered. Otherwise, a newly defined alias would kick out
the memory definition it is being aliased to.
* When defining a mem_alias, drop any existing one of that name.
* Actually use avr_find_memalias() to find aliases
* Add declaration for avr_find_memalias()
* When defining a memory, also search for an existing alias
If the newly defined name has the same as an existing alias, the alias
can be removed.
Note that we do explicitly *not* remove any memory by the same name of
a later defined alias, as this might invalidate another alias'es
pointer. If someone defines that, the alias name just won't ever be
found by avr_locate_mem().
2022-02-10 19:39:19 +00:00
|
|
|
match = m;
|
|
|
|
matches++;
|
2022-08-13 19:51:12 +00:00
|
|
|
if(m->desc[l] == 0) // Exact match between arg and memory
|
|
|
|
exact++;
|
Alias keyword (#868)
Implementation for an "alias" keyword.
By now, only applied inside memory descriptions.
* Make "mem_alias" a separate nonterminal.
The previous implementation attempt caused a syntax error in
yacc code, and separating mem_alias on the same level as
mem_spec appears to be the cleaner solution anyway.
* Maintain real memory aliases.
Instead of duplicating the aliased memory with a new name, maintain a
second list of memory aliases (per device) that contains a pointer to
the memory area it is aliased to. That way, a memory name can be
clearly distinguished between the canonical one and any aliases.
* Check p->mem_alias != NULL before touching it
* Add avr_find_memalias()
This takes a memory region as input, and searches whether an
alias can be found for it.
* We need to add a list structure for the mem_alias list, always.
By that means, mem_alias won't ever be NULL, so no need to check
later.
Also, in avr_dup_part(), duplicate the alias list.
* In a memory alias, actually remember the current name.
* In avr_dup_part(), adjust pointers of aliased memories
While walking the list of memories, for each entry, see if there is an
alias pointing to it. If so, allocate a duplicated one, and fix its
aliased_mem pointer to point to the duplicated memory region instead
of the original one.
* Add avr_locate_mem_noalias()
When looking whether any memory region has already been defined for
the current part while parsing the config file, only non-aliased names
must be considered. Otherwise, a newly defined alias would kick out
the memory definition it is being aliased to.
* When defining a mem_alias, drop any existing one of that name.
* Actually use avr_find_memalias() to find aliases
* Add declaration for avr_find_memalias()
* When defining a memory, also search for an existing alias
If the newly defined name has the same as an existing alias, the alias
can be removed.
Note that we do explicitly *not* remove any memory by the same name of
a later defined alias, as this might invalidate another alias'es
pointer. If someone defines that, the alias name just won't ever be
found by avr_locate_mem().
2022-02-10 19:39:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-13 19:51:12 +00:00
|
|
|
return exact == 1 || matches == 1? match: NULL;
|
Alias keyword (#868)
Implementation for an "alias" keyword.
By now, only applied inside memory descriptions.
* Make "mem_alias" a separate nonterminal.
The previous implementation attempt caused a syntax error in
yacc code, and separating mem_alias on the same level as
mem_spec appears to be the cleaner solution anyway.
* Maintain real memory aliases.
Instead of duplicating the aliased memory with a new name, maintain a
second list of memory aliases (per device) that contains a pointer to
the memory area it is aliased to. That way, a memory name can be
clearly distinguished between the canonical one and any aliases.
* Check p->mem_alias != NULL before touching it
* Add avr_find_memalias()
This takes a memory region as input, and searches whether an
alias can be found for it.
* We need to add a list structure for the mem_alias list, always.
By that means, mem_alias won't ever be NULL, so no need to check
later.
Also, in avr_dup_part(), duplicate the alias list.
* In a memory alias, actually remember the current name.
* In avr_dup_part(), adjust pointers of aliased memories
While walking the list of memories, for each entry, see if there is an
alias pointing to it. If so, allocate a duplicated one, and fix its
aliased_mem pointer to point to the duplicated memory region instead
of the original one.
* Add avr_locate_mem_noalias()
When looking whether any memory region has already been defined for
the current part while parsing the config file, only non-aliased names
must be considered. Otherwise, a newly defined alias would kick out
the memory definition it is being aliased to.
* When defining a mem_alias, drop any existing one of that name.
* Actually use avr_find_memalias() to find aliases
* Add declaration for avr_find_memalias()
* When defining a memory, also search for an existing alias
If the newly defined name has the same as an existing alias, the alias
can be removed.
Note that we do explicitly *not* remove any memory by the same name of
a later defined alias, as this might invalidate another alias'es
pointer. If someone defines that, the alias name just won't ever be
found by avr_locate_mem().
2022-02-10 19:39:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
AVRMEM *avr_locate_mem(const AVRPART *p, const char *desc) {
|
2022-08-13 19:51:12 +00:00
|
|
|
AVRMEM *m = avr_locate_mem_noalias(p, desc);
|
2022-07-07 17:32:19 +00:00
|
|
|
|
2022-08-13 19:51:12 +00:00
|
|
|
if(m)
|
|
|
|
return m;
|
Alias keyword (#868)
Implementation for an "alias" keyword.
By now, only applied inside memory descriptions.
* Make "mem_alias" a separate nonterminal.
The previous implementation attempt caused a syntax error in
yacc code, and separating mem_alias on the same level as
mem_spec appears to be the cleaner solution anyway.
* Maintain real memory aliases.
Instead of duplicating the aliased memory with a new name, maintain a
second list of memory aliases (per device) that contains a pointer to
the memory area it is aliased to. That way, a memory name can be
clearly distinguished between the canonical one and any aliases.
* Check p->mem_alias != NULL before touching it
* Add avr_find_memalias()
This takes a memory region as input, and searches whether an
alias can be found for it.
* We need to add a list structure for the mem_alias list, always.
By that means, mem_alias won't ever be NULL, so no need to check
later.
Also, in avr_dup_part(), duplicate the alias list.
* In a memory alias, actually remember the current name.
* In avr_dup_part(), adjust pointers of aliased memories
While walking the list of memories, for each entry, see if there is an
alias pointing to it. If so, allocate a duplicated one, and fix its
aliased_mem pointer to point to the duplicated memory region instead
of the original one.
* Add avr_locate_mem_noalias()
When looking whether any memory region has already been defined for
the current part while parsing the config file, only non-aliased names
must be considered. Otherwise, a newly defined alias would kick out
the memory definition it is being aliased to.
* When defining a mem_alias, drop any existing one of that name.
* Actually use avr_find_memalias() to find aliases
* Add declaration for avr_find_memalias()
* When defining a memory, also search for an existing alias
If the newly defined name has the same as an existing alias, the alias
can be removed.
Note that we do explicitly *not* remove any memory by the same name of
a later defined alias, as this might invalidate another alias'es
pointer. If someone defines that, the alias name just won't ever be
found by avr_locate_mem().
2022-02-10 19:39:19 +00:00
|
|
|
|
2022-08-13 19:51:12 +00:00
|
|
|
// Not yet found: look for matching alias name
|
|
|
|
AVRMEM_ALIAS *a = avr_locate_memalias(p, desc);
|
|
|
|
return a? a->aliased_mem: NULL;
|
Alias keyword (#868)
Implementation for an "alias" keyword.
By now, only applied inside memory descriptions.
* Make "mem_alias" a separate nonterminal.
The previous implementation attempt caused a syntax error in
yacc code, and separating mem_alias on the same level as
mem_spec appears to be the cleaner solution anyway.
* Maintain real memory aliases.
Instead of duplicating the aliased memory with a new name, maintain a
second list of memory aliases (per device) that contains a pointer to
the memory area it is aliased to. That way, a memory name can be
clearly distinguished between the canonical one and any aliases.
* Check p->mem_alias != NULL before touching it
* Add avr_find_memalias()
This takes a memory region as input, and searches whether an
alias can be found for it.
* We need to add a list structure for the mem_alias list, always.
By that means, mem_alias won't ever be NULL, so no need to check
later.
Also, in avr_dup_part(), duplicate the alias list.
* In a memory alias, actually remember the current name.
* In avr_dup_part(), adjust pointers of aliased memories
While walking the list of memories, for each entry, see if there is an
alias pointing to it. If so, allocate a duplicated one, and fix its
aliased_mem pointer to point to the duplicated memory region instead
of the original one.
* Add avr_locate_mem_noalias()
When looking whether any memory region has already been defined for
the current part while parsing the config file, only non-aliased names
must be considered. Otherwise, a newly defined alias would kick out
the memory definition it is being aliased to.
* When defining a mem_alias, drop any existing one of that name.
* Actually use avr_find_memalias() to find aliases
* Add declaration for avr_find_memalias()
* When defining a memory, also search for an existing alias
If the newly defined name has the same as an existing alias, the alias
can be removed.
Note that we do explicitly *not* remove any memory by the same name of
a later defined alias, as this might invalidate another alias'es
pointer. If someone defines that, the alias name just won't ever be
found by avr_locate_mem().
2022-02-10 19:39:19 +00:00
|
|
|
}
|
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
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;
|
|
|
|
}
|
Alias keyword (#868)
Implementation for an "alias" keyword.
By now, only applied inside memory descriptions.
* Make "mem_alias" a separate nonterminal.
The previous implementation attempt caused a syntax error in
yacc code, and separating mem_alias on the same level as
mem_spec appears to be the cleaner solution anyway.
* Maintain real memory aliases.
Instead of duplicating the aliased memory with a new name, maintain a
second list of memory aliases (per device) that contains a pointer to
the memory area it is aliased to. That way, a memory name can be
clearly distinguished between the canonical one and any aliases.
* Check p->mem_alias != NULL before touching it
* Add avr_find_memalias()
This takes a memory region as input, and searches whether an
alias can be found for it.
* We need to add a list structure for the mem_alias list, always.
By that means, mem_alias won't ever be NULL, so no need to check
later.
Also, in avr_dup_part(), duplicate the alias list.
* In a memory alias, actually remember the current name.
* In avr_dup_part(), adjust pointers of aliased memories
While walking the list of memories, for each entry, see if there is an
alias pointing to it. If so, allocate a duplicated one, and fix its
aliased_mem pointer to point to the duplicated memory region instead
of the original one.
* Add avr_locate_mem_noalias()
When looking whether any memory region has already been defined for
the current part while parsing the config file, only non-aliased names
must be considered. Otherwise, a newly defined alias would kick out
the memory definition it is being aliased to.
* When defining a mem_alias, drop any existing one of that name.
* Actually use avr_find_memalias() to find aliases
* Add declaration for avr_find_memalias()
* When defining a memory, also search for an existing alias
If the newly defined name has the same as an existing alias, the alias
can be removed.
Note that we do explicitly *not* remove any memory by the same name of
a later defined alias, as this might invalidate another alias'es
pointer. If someone defines that, the alias name just won't ever be
found by avr_locate_mem().
2022-02-10 19:39:19 +00:00
|
|
|
|
2003-11-30 16:42:10 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
void avr_mem_display(const char *prefix, FILE *f, const AVRMEM *m,
|
|
|
|
const AVRPART *p, int verbose) {
|
2022-07-26 22:43:56 +00:00
|
|
|
static unsigned int prev_mem_offset;
|
|
|
|
static int prev_mem_size;
|
2003-11-30 16:42:10 +00:00
|
|
|
int i, j;
|
|
|
|
char * optr;
|
|
|
|
|
2022-10-23 20:56:45 +00:00
|
|
|
if (m == NULL || verbose > 2) {
|
Mega-commit to bring in both, the STK500v2 support from Erik
Walthinsen, as well as JTAG ICE mkII support (by me).
Erik's submission has been cleaned up a little bit, mostly to add his
name and the current year to the copyright of the new file, remove
trailing white space before importing the files, and fix the minor
syntax errors in his avrdude.conf.in additions (missing semicolons).
The JTAG ICE mkII support should be considered alpha to beta quality
at this point. Few things are still to be done, like defering the
hfuse (OCDEN) tweaks until they are really required. Also, for
reasons not yet known, the target MCU doesn't start to run after
signing off from the ICE, it needs a power-cycle first (at least on my
STK500).
Note that for the JTAG ICE, I did change a few things in the internal
API. Notably I made the serial receive timeout configurable by the
backends via an exported variable (done in both the Posix and the
Win32 implementation), and I made the serial_recv() function return a
-1 instead of bailing out with exit(1) upon encountering a receive
timeout (currently only done in the Posix implementation). Both
measures together allow me to receive a datastreem from the ICE at 115
kbps on a somewhat lossy PCI multi-UART card that occasionally drops a
character. The JTAG ICE mkII protocol has enough of safety layers to
allow recovering from these events, but the previous code wasn't
prepared for any kind of recovery. The Win32 change for this still
has to be done, and the traditional drivers need to be converted to
exit(1) upon encountering a timeout (as they're now getting a -1
returned they didn't see before in that case).
git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@451 81a1dc3b-b13d-400b-aceb-764788c761c2
2005-05-10 19:17:12 +00:00
|
|
|
fprintf(f,
|
2022-01-17 19:53:00 +00:00
|
|
|
"%s Block Poll Page Polled\n"
|
|
|
|
"%sMemory Type Alias Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack\n"
|
|
|
|
"%s----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------\n",
|
2003-11-30 16:42:10 +00:00
|
|
|
prefix, prefix, prefix);
|
|
|
|
}
|
2022-01-17 19:53:00 +00:00
|
|
|
|
2022-10-23 20:56:45 +00:00
|
|
|
if (m != NULL) {
|
2022-01-17 19:53:00 +00:00
|
|
|
// Only print memory section if the previous section printed isn't identical
|
|
|
|
if(prev_mem_offset != m->offset || prev_mem_size != m->size || (strcmp(p->family_id, "") == 0)) {
|
2022-01-08 22:57:37 +00:00
|
|
|
prev_mem_offset = m->offset;
|
|
|
|
prev_mem_size = m->size;
|
Alias keyword (#868)
Implementation for an "alias" keyword.
By now, only applied inside memory descriptions.
* Make "mem_alias" a separate nonterminal.
The previous implementation attempt caused a syntax error in
yacc code, and separating mem_alias on the same level as
mem_spec appears to be the cleaner solution anyway.
* Maintain real memory aliases.
Instead of duplicating the aliased memory with a new name, maintain a
second list of memory aliases (per device) that contains a pointer to
the memory area it is aliased to. That way, a memory name can be
clearly distinguished between the canonical one and any aliases.
* Check p->mem_alias != NULL before touching it
* Add avr_find_memalias()
This takes a memory region as input, and searches whether an
alias can be found for it.
* We need to add a list structure for the mem_alias list, always.
By that means, mem_alias won't ever be NULL, so no need to check
later.
Also, in avr_dup_part(), duplicate the alias list.
* In a memory alias, actually remember the current name.
* In avr_dup_part(), adjust pointers of aliased memories
While walking the list of memories, for each entry, see if there is an
alias pointing to it. If so, allocate a duplicated one, and fix its
aliased_mem pointer to point to the duplicated memory region instead
of the original one.
* Add avr_locate_mem_noalias()
When looking whether any memory region has already been defined for
the current part while parsing the config file, only non-aliased names
must be considered. Otherwise, a newly defined alias would kick out
the memory definition it is being aliased to.
* When defining a mem_alias, drop any existing one of that name.
* Actually use avr_find_memalias() to find aliases
* Add declaration for avr_find_memalias()
* When defining a memory, also search for an existing alias
If the newly defined name has the same as an existing alias, the alias
can be removed.
Note that we do explicitly *not* remove any memory by the same name of
a later defined alias, as this might invalidate another alias'es
pointer. If someone defines that, the alias name just won't ever be
found by avr_locate_mem().
2022-02-10 19:39:19 +00:00
|
|
|
AVRMEM_ALIAS *ap = avr_find_memalias(p, m);
|
2022-01-17 19:53:00 +00:00
|
|
|
/* 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 */
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
const char *mem_desc_alias = ap? ap->desc: "";
|
2022-01-08 22:57:37 +00:00
|
|
|
fprintf(f,
|
2022-01-17 19:53:00 +00:00
|
|
|
"%s%-11s %-8s %4d %5d %5d %4d %-6s %6d %4d %6d %5d %5d 0x%02x 0x%02x\n",
|
|
|
|
prefix,
|
|
|
|
m->desc,
|
|
|
|
mem_desc_alias,
|
|
|
|
m->mode, m->delay, m->blocksize, m->pollindex,
|
2022-01-08 22:57:37 +00:00
|
|
|
m->paged ? "yes" : "no",
|
|
|
|
m->size,
|
|
|
|
m->page_size,
|
|
|
|
m->num_pages,
|
|
|
|
m->min_write_delay,
|
|
|
|
m->max_write_delay,
|
|
|
|
m->readback[0],
|
|
|
|
m->readback[1]);
|
|
|
|
}
|
2006-07-21 21:51:13 +00:00
|
|
|
if (verbose > 4) {
|
2022-10-17 14:44:55 +00:00
|
|
|
msg_trace2("%s Memory Ops:\n"
|
2014-05-18 08:41:46 +00:00
|
|
|
"%s Oeration Inst Bit Bit Type Bitno Value\n"
|
|
|
|
"%s ----------- -------- -------- ----- -----\n",
|
|
|
|
prefix, prefix, prefix);
|
2003-11-30 16:42:10 +00:00
|
|
|
for (i=0; i<AVR_OP_MAX; i++) {
|
|
|
|
if (m->op[i]) {
|
|
|
|
for (j=31; j>=0; j--) {
|
|
|
|
if (j==31)
|
|
|
|
optr = avr_op_str(i);
|
|
|
|
else
|
|
|
|
optr = " ";
|
|
|
|
fprintf(f,
|
|
|
|
"%s %-11s %8d %8s %5d %5d\n",
|
|
|
|
prefix, optr, j,
|
|
|
|
bittype(m->op[i]->bit[j].type),
|
|
|
|
m->op[i]->bit[j].bitno,
|
|
|
|
m->op[i]->bit[j].value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Elementary functions dealing with AVRPART structures
|
|
|
|
*/
|
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
AVRPART *avr_new_part(void) {
|
|
|
|
AVRPART *p = (AVRPART *) cfg_malloc("avr_new_part()", sizeof(AVRPART));
|
2022-08-08 15:52:09 +00:00
|
|
|
const char *nulp = cache_string("");
|
2003-11-30 16:42:10 +00:00
|
|
|
|
|
|
|
memset(p, 0, sizeof(*p));
|
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
// Initialise const char * and LISTID entities
|
|
|
|
p->desc = nulp;
|
|
|
|
p->id = nulp;
|
2022-08-07 13:05:54 +00:00
|
|
|
p->parent_id = nulp;
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
p->family_id = nulp;
|
2022-08-07 13:05:54 +00:00
|
|
|
p->config_file = nulp;
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
p->mem = lcreat(NULL, 0);
|
|
|
|
p->mem_alias = lcreat(NULL, 0);
|
|
|
|
|
|
|
|
// Default values
|
2022-08-30 18:48:17 +00:00
|
|
|
p->mcuid = -1;
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
p->hvupdi_variant = -1;
|
2022-11-25 19:20:45 +00:00
|
|
|
p->autobaud_sync = 0x30; // STK_GET_SYNC
|
2006-02-27 17:18:42 +00:00
|
|
|
memset(p->signature, 0xFF, 3);
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
p->reset_disposition = RESET_DEDICATED;
|
|
|
|
p->retry_pulse = PIN_AVR_SCK;
|
|
|
|
p->flags = AVRPART_SERIALOK | AVRPART_PARALLELOK | AVRPART_ENABLEPAGEPROGRAMMING;
|
2006-07-16 21:30:14 +00:00
|
|
|
p->ctl_stack_type = CTL_STACK_NONE;
|
2012-12-04 13:59:37 +00:00
|
|
|
p->ocdrev = -1;
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
p->lineno = 0;
|
2003-11-30 16:42:10 +00:00
|
|
|
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
AVRPART *avr_dup_part(const AVRPART *d) {
|
|
|
|
AVRPART *p = avr_new_part();
|
2003-11-30 16:42:10 +00:00
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
if(d) {
|
|
|
|
*p = *d;
|
2003-11-30 16:42:10 +00:00
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
// Duplicate the memory and alias chains
|
|
|
|
p->mem = lcreat(NULL, 0);
|
|
|
|
p->mem_alias = lcreat(NULL, 0);
|
2003-11-30 16:42:10 +00:00
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
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);
|
|
|
|
}
|
Alias keyword (#868)
Implementation for an "alias" keyword.
By now, only applied inside memory descriptions.
* Make "mem_alias" a separate nonterminal.
The previous implementation attempt caused a syntax error in
yacc code, and separating mem_alias on the same level as
mem_spec appears to be the cleaner solution anyway.
* Maintain real memory aliases.
Instead of duplicating the aliased memory with a new name, maintain a
second list of memory aliases (per device) that contains a pointer to
the memory area it is aliased to. That way, a memory name can be
clearly distinguished between the canonical one and any aliases.
* Check p->mem_alias != NULL before touching it
* Add avr_find_memalias()
This takes a memory region as input, and searches whether an
alias can be found for it.
* We need to add a list structure for the mem_alias list, always.
By that means, mem_alias won't ever be NULL, so no need to check
later.
Also, in avr_dup_part(), duplicate the alias list.
* In a memory alias, actually remember the current name.
* In avr_dup_part(), adjust pointers of aliased memories
While walking the list of memories, for each entry, see if there is an
alias pointing to it. If so, allocate a duplicated one, and fix its
aliased_mem pointer to point to the duplicated memory region instead
of the original one.
* Add avr_locate_mem_noalias()
When looking whether any memory region has already been defined for
the current part while parsing the config file, only non-aliased names
must be considered. Otherwise, a newly defined alias would kick out
the memory definition it is being aliased to.
* When defining a mem_alias, drop any existing one of that name.
* Actually use avr_find_memalias() to find aliases
* Add declaration for avr_find_memalias()
* When defining a memory, also search for an existing alias
If the newly defined name has the same as an existing alias, the alias
can be removed.
Note that we do explicitly *not* remove any memory by the same name of
a later defined alias, as this might invalidate another alias'es
pointer. If someone defines that, the alias name just won't ever be
found by avr_locate_mem().
2022-02-10 19:39:19 +00:00
|
|
|
}
|
|
|
|
}
|
2003-11-30 16:42:10 +00:00
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
for(int i = 0; i < AVR_OP_MAX; i++)
|
|
|
|
p->op[i] = avr_dup_opcode(p->op[i]);
|
2011-12-29 16:51:44 +00:00
|
|
|
}
|
|
|
|
|
2003-11-30 16:42:10 +00:00
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2012-01-17 20:56:37 +00:00
|
|
|
void avr_free_part(AVRPART * d)
|
|
|
|
{
|
2022-07-26 22:43:56 +00:00
|
|
|
ldestroy_cb(d->mem, (void(*)(void *))avr_free_mem);
|
|
|
|
d->mem = NULL;
|
|
|
|
ldestroy_cb(d->mem_alias, (void(*)(void *))avr_free_memalias);
|
|
|
|
d->mem_alias = NULL;
|
|
|
|
/* do not free d->parent_id and d->config_file */
|
|
|
|
for(size_t i=0; i<sizeof(d->op)/sizeof(d->op[0]); i++) {
|
|
|
|
if (d->op[i] != NULL) {
|
|
|
|
avr_free_opcode(d->op[i]);
|
|
|
|
d->op[i] = NULL;
|
2012-01-17 20:56:37 +00:00
|
|
|
}
|
2022-07-26 22:43:56 +00:00
|
|
|
}
|
|
|
|
free(d);
|
2012-01-17 20:56:37 +00:00
|
|
|
}
|
2003-11-30 16:42:10 +00:00
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
AVRPART *locate_part(const LISTID parts, const char *partdesc) {
|
2003-11-30 16:49:00 +00:00
|
|
|
AVRPART * p = NULL;
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
int found = 0;
|
2003-11-30 16:49:00 +00:00
|
|
|
|
2022-07-07 17:32:19 +00:00
|
|
|
if(!parts || !partdesc)
|
|
|
|
return NULL;
|
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
for (LNODEID ln1=lfirst(parts); ln1 && !found; ln1=lnext(ln1)) {
|
2003-11-30 16:49:00 +00:00
|
|
|
p = ldata(ln1);
|
|
|
|
if ((strcasecmp(partdesc, p->id) == 0) ||
|
|
|
|
(strcasecmp(partdesc, p->desc) == 0))
|
|
|
|
found = 1;
|
|
|
|
}
|
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
return found? p: NULL;
|
2003-11-30 16:49:00 +00:00
|
|
|
}
|
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
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;
|
|
|
|
}
|
2004-01-12 22:48:50 +00:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
2003-11-30 16:49:00 +00:00
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
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])
|
2014-08-18 21:43:08 +00:00
|
|
|
break;
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
if(i == 3)
|
2014-08-18 21:43:08 +00:00
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-01-29 20:41:47 +00:00
|
|
|
/*
|
|
|
|
* Iterate over the list of avrparts given as "avrparts", and
|
|
|
|
* call the callback function cb for each entry found. cb is being
|
|
|
|
* passed the following arguments:
|
|
|
|
* . the name of the avrpart (for -p)
|
|
|
|
* . the descriptive text given in the config file
|
|
|
|
* . the name of the config file this avrpart has been defined in
|
|
|
|
* . the line number of the config file this avrpart has been defined at
|
|
|
|
* . the "cookie" passed into walk_avrparts() (opaque client data)
|
|
|
|
*/
|
|
|
|
void walk_avrparts(LISTID avrparts, walk_avrparts_cb cb, void *cookie)
|
2003-11-30 16:49:00 +00:00
|
|
|
{
|
|
|
|
LNODEID ln1;
|
|
|
|
AVRPART * p;
|
|
|
|
|
2007-01-29 20:41:47 +00:00
|
|
|
for (ln1 = lfirst(avrparts); ln1; ln1 = lnext(ln1)) {
|
2003-11-30 16:49:00 +00:00
|
|
|
p = ldata(ln1);
|
2007-01-29 20:41:47 +00:00
|
|
|
cb(p->id, p->desc, p->config_file, p->lineno, cookie);
|
2003-11-30 16:49:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-16 20:44:07 +00:00
|
|
|
/*
|
|
|
|
* Compare function to sort the list of programmers
|
|
|
|
*/
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
static int sort_avrparts_compare(const AVRPART *p1, const AVRPART *p2) {
|
|
|
|
if(p1 == NULL || p1->desc == NULL || p2 == NULL || p2->desc == NULL)
|
2011-12-16 20:44:07 +00:00
|
|
|
return 0;
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
|
|
|
|
return strcasecmp(p1->desc, p2->desc);
|
2011-12-16 20:44:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Sort the list of programmers given as "programmers"
|
|
|
|
*/
|
|
|
|
void sort_avrparts(LISTID avrparts)
|
|
|
|
{
|
|
|
|
lsort(avrparts,(int (*)(void*, void*)) sort_avrparts_compare);
|
|
|
|
}
|
2003-11-30 16:49:00 +00:00
|
|
|
|
2007-01-29 20:41:47 +00:00
|
|
|
|
2007-01-24 22:43:46 +00:00
|
|
|
static char * reset_disp_str(int r)
|
2003-11-30 16:42:10 +00:00
|
|
|
{
|
|
|
|
switch (r) {
|
|
|
|
case RESET_DEDICATED : return "dedicated";
|
|
|
|
case RESET_IO : return "possible i/o";
|
|
|
|
default : return "<invalid>";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
void avr_display(FILE *f, const AVRPART *p, const char *prefix, int verbose) {
|
2003-11-30 16:42:10 +00:00
|
|
|
char * buf;
|
2007-01-30 13:41:54 +00:00
|
|
|
const char * px;
|
2003-11-30 16:42:10 +00:00
|
|
|
LNODEID ln;
|
|
|
|
AVRMEM * m;
|
|
|
|
|
2022-01-09 17:13:07 +00:00
|
|
|
fprintf( f, "%sAVR Part : %s\n", prefix, p->desc);
|
|
|
|
if (p->chip_erase_delay)
|
|
|
|
fprintf(f, "%sChip Erase delay : %d us\n", prefix, p->chip_erase_delay);
|
|
|
|
if (p->pagel)
|
|
|
|
fprintf(f, "%sPAGEL : P%02X\n", prefix, p->pagel);
|
|
|
|
if (p->bs2)
|
|
|
|
fprintf(f, "%sBS2 : P%02X\n", prefix, p->bs2);
|
|
|
|
fprintf( f, "%sRESET disposition : %s\n", prefix, reset_disp_str(p->reset_disposition));
|
|
|
|
fprintf( f, "%sRETRY pulse : %s\n", prefix, avr_pin_name(p->retry_pulse));
|
|
|
|
fprintf( f, "%sSerial program mode : %s\n", prefix, (p->flags & AVRPART_SERIALOK) ? "yes" : "no");
|
|
|
|
fprintf( f, "%sParallel program mode : %s\n", prefix, (p->flags & AVRPART_PARALLELOK) ?
|
|
|
|
((p->flags & AVRPART_PSEUDOPARALLEL) ? "pseudo" : "yes") : "no");
|
|
|
|
if(p->timeout)
|
|
|
|
fprintf(f, "%sTimeout : %d\n", prefix, p->timeout);
|
|
|
|
if(p->stabdelay)
|
|
|
|
fprintf(f, "%sStabDelay : %d\n", prefix, p->stabdelay);
|
|
|
|
if(p->cmdexedelay)
|
|
|
|
fprintf(f, "%sCmdexeDelay : %d\n", prefix, p->cmdexedelay);
|
|
|
|
if(p->synchloops)
|
|
|
|
fprintf(f, "%sSyncLoops : %d\n", prefix, p->synchloops);
|
|
|
|
if(p->bytedelay)
|
|
|
|
fprintf(f, "%sByteDelay : %d\n", prefix, p->bytedelay);
|
|
|
|
if(p->pollindex)
|
|
|
|
fprintf(f, "%sPollIndex : %d\n", prefix, p->pollindex);
|
|
|
|
if(p->pollvalue)
|
|
|
|
fprintf(f, "%sPollValue : 0x%02x\n", prefix, p->pollvalue);
|
|
|
|
fprintf( f, "%sMemory Detail :\n\n", prefix);
|
2003-11-30 16:42:10 +00:00
|
|
|
|
|
|
|
px = prefix;
|
2022-10-17 14:44:55 +00:00
|
|
|
buf = (char *) cfg_malloc("avr_display()", strlen(prefix) + 5);
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
strcpy(buf, prefix);
|
|
|
|
strcat(buf, " ");
|
|
|
|
px = buf;
|
|
|
|
|
|
|
|
if (verbose <= 2)
|
|
|
|
avr_mem_display(px, f, NULL, p, verbose);
|
2003-11-30 16:42:10 +00:00
|
|
|
|
|
|
|
for (ln=lfirst(p->mem); ln; ln=lnext(ln)) {
|
|
|
|
m = ldata(ln);
|
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.
2022-08-10 15:14:56 +00:00
|
|
|
avr_mem_display(px, f, m, p, verbose);
|
2003-11-30 16:42:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (buf)
|
|
|
|
free(buf);
|
|
|
|
}
|
2022-07-26 23:12:57 +00:00
|
|
|
|
|
|
|
|
|
|
|
char cmdbitchar(CMDBIT cb) {
|
|
|
|
switch(cb.type) {
|
|
|
|
case AVR_CMDBIT_IGNORE:
|
|
|
|
return 'x';
|
|
|
|
case AVR_CMDBIT_VALUE:
|
|
|
|
return cb.value? '1': '0';
|
|
|
|
case AVR_CMDBIT_ADDRESS:
|
|
|
|
return 'a';
|
|
|
|
case AVR_CMDBIT_INPUT:
|
|
|
|
return 'i';
|
|
|
|
case AVR_CMDBIT_OUTPUT:
|
|
|
|
return 'o';
|
|
|
|
default:
|
|
|
|
return '?';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
char *cmdbitstr(CMDBIT cb) {
|
|
|
|
char space[32];
|
|
|
|
|
|
|
|
*space = cmdbitchar(cb);
|
|
|
|
if(*space == 'a')
|
|
|
|
sprintf(space+1, "%d", cb.bitno);
|
|
|
|
else
|
|
|
|
space[1] = 0;
|
|
|
|
|
2022-08-09 20:20:44 +00:00
|
|
|
return cfg_strdup("cmdbitstr()", space);
|
2022-07-26 23:12:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const char *opcodename(int opnum) {
|
|
|
|
switch(opnum) {
|
|
|
|
case AVR_OP_READ:
|
|
|
|
return "read";
|
|
|
|
case AVR_OP_WRITE:
|
|
|
|
return "write";
|
|
|
|
case AVR_OP_READ_LO:
|
|
|
|
return "read_lo";
|
|
|
|
case AVR_OP_READ_HI:
|
|
|
|
return "read_hi";
|
|
|
|
case AVR_OP_WRITE_LO:
|
|
|
|
return "write_lo";
|
|
|
|
case AVR_OP_WRITE_HI:
|
|
|
|
return "write_hi";
|
|
|
|
case AVR_OP_LOADPAGE_LO:
|
|
|
|
return "loadpage_lo";
|
|
|
|
case AVR_OP_LOADPAGE_HI:
|
|
|
|
return "loadpage_hi";
|
|
|
|
case AVR_OP_LOAD_EXT_ADDR:
|
|
|
|
return "load_ext_addr";
|
|
|
|
case AVR_OP_WRITEPAGE:
|
|
|
|
return "writepage";
|
|
|
|
case AVR_OP_CHIP_ERASE:
|
|
|
|
return "chip_erase";
|
|
|
|
case AVR_OP_PGM_ENABLE:
|
|
|
|
return "pgm_enable";
|
|
|
|
default:
|
|
|
|
return "???";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Unique string representation of an opcode
|
2022-08-23 15:57:09 +00:00
|
|
|
char *opcode2str(const OPCODE *op, int opnum, int detailed) {
|
2022-07-26 23:12:57 +00:00
|
|
|
char cb, space[1024], *sp = space;
|
|
|
|
int compact = 1;
|
|
|
|
|
|
|
|
if(!op)
|
2022-08-09 20:20:44 +00:00
|
|
|
return cfg_strdup("opcode2str()", "NULL");
|
2022-07-26 23:12:57 +00:00
|
|
|
|
|
|
|
// Can the opcode be printed in a compact way? Only if address bits are systematic.
|
|
|
|
for(int i=31; i >= 0; i--)
|
|
|
|
if(op->bit[i].type == AVR_CMDBIT_ADDRESS)
|
|
|
|
if(i<8 || i>23 || op->bit[i].bitno != (opnum == AVR_OP_LOAD_EXT_ADDR? i+8: i-8))
|
|
|
|
compact = 0;
|
|
|
|
|
|
|
|
if(detailed)
|
|
|
|
*sp++ = '"';
|
|
|
|
|
|
|
|
for(int i=31; i >= 0; i--) {
|
|
|
|
*sp++ = cb = cmdbitchar(op->bit[i]);
|
|
|
|
if(compact) {
|
|
|
|
if(i && i%8 == 0)
|
|
|
|
*sp++ = '-', *sp++ = '-';
|
|
|
|
else if(i && i%4 == 0)
|
|
|
|
*sp++ = '.';
|
|
|
|
} else {
|
|
|
|
if(cb == 'a') {
|
|
|
|
sprintf(sp, "%d", op->bit[i].bitno);
|
|
|
|
sp += strlen(sp);
|
|
|
|
}
|
|
|
|
if(i) {
|
|
|
|
if(detailed)
|
|
|
|
*sp++ = ' ';
|
|
|
|
if(i%8 == 0)
|
|
|
|
*sp++ = ' ';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(detailed)
|
|
|
|
*sp++ = '"';
|
|
|
|
*sp = 0;
|
|
|
|
|
2022-08-09 20:20:44 +00:00
|
|
|
return cfg_strdup("opcode2str()", space);
|
2022-07-26 23:12:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Match STRING against the partname pattern PATTERN, returning 1 if it
|
|
|
|
* matches, 0 if not. NOTE: part_match() is a modified old copy of !fnmatch()
|
|
|
|
* from the GNU C Library (published under GLP v2). Used for portability.
|
|
|
|
*/
|
|
|
|
|
|
|
|
inline static int fold(int c) {
|
|
|
|
return (c >= 'A' && c <= 'Z')? c+('a'-'A'): c;
|
|
|
|
}
|
|
|
|
|
|
|
|
int part_match(const char *pattern, const char *string) {
|
|
|
|
unsigned char c;
|
|
|
|
const char *p = pattern, *n = string;
|
|
|
|
|
|
|
|
if(!*n) // AVRDUDE specialty: empty string never matches
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
while((c = fold(*p++))) {
|
|
|
|
switch(c) {
|
|
|
|
case '?':
|
|
|
|
if(*n == 0)
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '\\':
|
|
|
|
c = fold(*p++);
|
|
|
|
if(fold(*n) != c)
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '*':
|
|
|
|
for(c = *p++; c == '?' || c == '*'; c = *p++)
|
|
|
|
if(c == '?' && *n++ == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if(c == 0)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
{
|
|
|
|
unsigned char c1 = fold(c == '\\'? *p : c); // This char
|
|
|
|
|
|
|
|
for(--p; *n; ++n) // Recursively check reminder of string for *
|
|
|
|
if((c == '[' || fold(*n) == c1) && part_match(p, n) == 1)
|
|
|
|
return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
case '[':
|
|
|
|
{
|
|
|
|
int negate;
|
|
|
|
|
|
|
|
if(*n == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
negate = (*p == '!' || *p == '^');
|
|
|
|
if(negate)
|
|
|
|
++p;
|
|
|
|
|
|
|
|
c = *p++;
|
|
|
|
for(;;) {
|
|
|
|
unsigned char cstart = c, cend = c;
|
|
|
|
|
|
|
|
if(c == '\\')
|
|
|
|
cstart = cend = *p++;
|
|
|
|
|
|
|
|
cstart = cend = fold(cstart);
|
|
|
|
|
|
|
|
if(c == 0) // [ (unterminated)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
c = *p++;
|
|
|
|
c = fold(c);
|
|
|
|
|
|
|
|
if(c == '-' && *p != ']') {
|
|
|
|
cend = *p++;
|
|
|
|
if(cend == '\\')
|
|
|
|
cend = *p++;
|
|
|
|
if(cend == 0)
|
|
|
|
return 0;
|
|
|
|
cend = fold(cend);
|
|
|
|
|
|
|
|
c = *p++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(fold(*n) >= cstart && fold(*n) <= cend)
|
|
|
|
goto matched;
|
|
|
|
|
|
|
|
if(c == ']')
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(!negate)
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
matched:;
|
|
|
|
while(c != ']') { // Skip the rest of the [...] that already matched
|
|
|
|
|
|
|
|
if(c == 0) // [... (unterminated)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
c = *p++;
|
|
|
|
if(c == '\\') // XXX 1003.2d11 is unclear if this is right
|
|
|
|
++p;
|
|
|
|
}
|
|
|
|
if(negate)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
if(c != fold(*n))
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
++n;
|
|
|
|
}
|
|
|
|
|
|
|
|
return *n == 0;
|
|
|
|
}
|