Skip to content

Commit

Permalink
Provide avr_locate_upidx(), avr_locate_configitems(), avr_locate_conf…
Browse files Browse the repository at this point in the history
…iglist()
  • Loading branch information
stefanrueger committed Nov 26, 2023
1 parent 65901cf commit f4de378
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 41 deletions.
114 changes: 87 additions & 27 deletions src/avrpart.c
Original file line number Diff line number Diff line change
Expand Up @@ -493,50 +493,105 @@ AVRMEM_ALIAS *avr_find_memalias(const AVRPART *p, const AVRMEM *m_orig) {
return NULL;
}

const Configitem_t *avr_locate_config(const Configitem_t *cfg, int nc, const char *name) {
const Configitem_t *match = NULL;
int matches = 0, n1;
// Return index in uP_table for part or -1
int avr_locate_upidx(const AVRPART *p) {
int idx = -1;

if(!p)
return -1;
if(p->mcuid >= 0)
idx = upidxmcuid(p->mcuid);
if(idx < 0 && p->desc && *p->desc)
idx = upidxname(p->desc);

if(idx < 0)
pmsg_error("uP_table neither knows mcuid %d nor part %s\n",
p->mcuid, p->desc && *p->desc? p->desc: "???");

return idx;
}

if(!cfg || !name || !(n1 = *name))
// Return pointer to config table for the part and set number of config bitfields
const Configitem_t *avr_locate_configitems(const AVRPART *p, int *nc) {
int idx = avr_locate_upidx(p);
if(idx < 0)
return NULL;

size_t l = strlen(name);
*nc = uP_table[idx].nconfigs;
return uP_table[idx].cfgtable;
}


/*
* Return pointer to a configuration bitfield that uniquely matches the
* argument name. Return NULL if none matches or more than one do.
*
* The caller provides a matching function which can be str_eq, str_starts,
* str_matched_by etc. If name is the full name of a configuration bitfield
* then a pointer to that is returned irrespective of the matching function.
*/
const Configitem_t *avr_locate_config(const Configitem_t *cfg, int nc, const char *name,
int (*match)(const char *, const char*)) {

if(!cfg || nc < 1 || !name || !match)
return NULL;

const Configitem_t *ret = NULL;
int nmatches = 0;

for(int i = 0; i < nc; i++) {
if(n1 == *cfg[i].name && !strncmp(cfg[i].name, name, l)) { // Partial initial match
match = cfg+i;
matches++;
if(cfg[i].name[l] == 0) // Exact match; return straight away
return match;
if(match(cfg[i].name, name)) {
if(match == str_eq || str_eq(cfg[i].name, name)) // Full name specified: return straight away
return cfg+i;
nmatches++, ret = cfg+i;
}
}

return matches == 1? match: NULL;
return nmatches == 1? ret: NULL;
}

/*
* Return a NULL terminated malloc'd list of pointers to config bitfields
*
* The caller provides a matching function which can be str_eq, str_starts,
* str_matched_by etc. If name is a full, existing config name then the
* returned list is confined to this specific entry irrespective of the
* matching function.
*/
const Configitem_t **avr_locate_configlist(const Configitem_t *cfg, int nc, const char *name,
int (*match)(const char *, const char*)) {

const Configitem_t **ret = cfg_malloc(__func__, sizeof cfg*(nc>0? nc+1: 1)), **r = ret;

if(cfg && name && match) {
for(int i = 0; i < nc; i++)
if(match(cfg[i].name, name)) {
if(match == str_eq || str_eq(cfg[i].name, name)) { // Full name specified: return straight away
ret[0] = cfg+i;
ret[1] = NULL;
return ret;
}
*r++ = cfg+i;
}
}
*r = NULL;

return ret;
}

// Return memory associated with config item and fill in pointer to Configitem_t record
static AVRMEM *avr_locate_config_mem_c_value(const PROGRAMMER *pgm, const AVRPART *p,
const char *cname, const Configitem_t **cp, int *valp) {

int idx = -1;
int nc = 0;
const Configitem_t *cfg = avr_locate_configitems(p, &nc);

if(p->mcuid >= 0)
idx = upidxmcuid(p->mcuid);
if(idx < 0 && p->desc && *p->desc)
idx = upidxname(p->desc);
if(idx < 0) {
pmsg_error("uP_table neither knows mcuid %d nor part %s\n",
p->mcuid, p->desc && *p->desc? p->desc: "???");
if(!cfg || nc < 1) {
pmsg_error("avrintel.c does not hold configuration information for %s\n", p->desc);
return NULL;
}

int nc = uP_table[idx].nconfigs;
const Configitem_t *cfg = uP_table[idx].cfgtable;
if(nc < 1 || !cfg) {
pmsg_error("%s does not have config information in avrintel.c\n", p->desc);
return NULL;
}

const Configitem_t *c = avr_locate_config(cfg, nc, cname);
const Configitem_t *c = avr_locate_config(cfg, nc, cname, str_contains);
if(!c) {
pmsg_error("%s does not have a unique config item matched by %s\n", p->desc, cname);
return NULL;
Expand Down Expand Up @@ -567,6 +622,7 @@ static AVRMEM *avr_locate_config_mem_c_value(const PROGRAMMER *pgm, const AVRPAR
return mem;
}

// Initialise *valuep with configuration value of named configuration bitfield
int avr_get_config_value(const PROGRAMMER *pgm, const AVRPART *p, const char *cname, int *valuep) {
const Configitem_t *c;
int fusel;
Expand All @@ -578,6 +634,7 @@ int avr_get_config_value(const PROGRAMMER *pgm, const AVRPART *p, const char *cn
return 0;
}

// Set configuration value of named configuration bitfield to value
int avr_set_config_value(const PROGRAMMER *pgm, const AVRPART *p, const char *cname, int value) {
AVRMEM *mem;
const Configitem_t *c;
Expand All @@ -586,6 +643,9 @@ int avr_set_config_value(const PROGRAMMER *pgm, const AVRPART *p, const char *cn
if(!(mem=avr_locate_config_mem_c_value(pgm, p, cname, &c, &fusel)))
return -1;

if((value << c->lsh) & ~c->mask)
pmsg_warning("value 0x%02x has bits set outside bitfield mask 0x%02x\n", value, c->mask >> c->lsh);

int newval = (fusel & ~c->mask) | ((value << c->lsh) & c->mask);

if(newval != fusel) {
Expand Down
7 changes: 6 additions & 1 deletion src/libavrdude.h
Original file line number Diff line number Diff line change
Expand Up @@ -1420,7 +1420,12 @@ typedef struct {
extern "C" {
#endif

const Configitem_t *avr_locate_config(const Configitem_t *cfg, int nc, const char *name);
int avr_locate_upidx(const AVRPART *p);
const Configitem_t *avr_locate_configitems(const AVRPART *p, int *nc);
const Configitem_t *avr_locate_config(const Configitem_t *cfg, int nc, const char *name,
int (*match)(const char *, const char*));
const Configitem_t **avr_locate_configlist(const Configitem_t *cfg, int nc, const char *name,
int (*match)(const char *, const char*));
int avr_get_config_value(const PROGRAMMER *pgm, const AVRPART *p, const char *cname, int *valuep);
int avr_set_config_value(const PROGRAMMER *pgm, const AVRPART *p, const char *cname, int value);

Expand Down
30 changes: 17 additions & 13 deletions src/term.c
Original file line number Diff line number Diff line change
Expand Up @@ -1999,29 +1999,33 @@ static char *tokenize(char *s, int *argcp, char ***argvp) {


static int do_cmd(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) {
int i;
int hold, matches;
size_t len;

len = strlen(argv[0]);
matches = 0;
for (i=0; i<NCMDS; i++) {
if(!*(void (**)(void)) ((char *) pgm + cmd[i].fnoff))
continue;
if(len && strncasecmp(argv[0], cmd[i].name, len)==0) { // Partial initial match
hold = i;
matches++;
if(cmd[i].name[len] == 0) { // Exact match
matches = 1;
break;
for(int i = 0; i < NCMDS; i++)
if(*(void (**)(void)) ((char *) pgm + cmd[i].fnoff))
if(len && strncasecmp(argv[0], cmd[i].name, len)==0) { // Partial initial match
hold = i;
matches++;
if(cmd[i].name[len] == 0) { // Exact match
matches = 1;
break;
}
}
}
}

if(matches == 1)
return cmd[hold].func(pgm, p, argc, argv);

pmsg_error("(cmd) command %s is %s\n", argv[0], matches > 1? "ambiguous": "invalid");
pmsg_error("(cmd) command %s is %s", argv[0], matches > 1? "ambiguous": "invalid");
if(matches > 1)
for(int ch = ':', i = 0; i < NCMDS; i++)
if(*(void (**)(void)) ((char *) pgm + cmd[i].fnoff))
if(len && strncasecmp(argv[0], cmd[i].name, len)==0)
msg_error("%c %s", ch, cmd[i].name), ch = ',';
msg_error("\n");

return -1;
}

Expand Down

0 comments on commit f4de378

Please sign in to comment.