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().
This commit is contained in:
parent
ba314f23e9
commit
d134dc8fff
144
src/avrpart.c
144
src/avrpart.c
|
@ -260,6 +260,21 @@ AVRMEM * avr_new_memtype(void)
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AVRMEM_ALIAS * avr_new_memalias(void)
|
||||||
|
{
|
||||||
|
AVRMEM_ALIAS * m;
|
||||||
|
|
||||||
|
m = (AVRMEM_ALIAS *)malloc(sizeof(*m));
|
||||||
|
if (m == NULL) {
|
||||||
|
avrdude_message(MSG_INFO, "avr_new_memalias(): out of memory\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(m, 0, sizeof(*m));
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate and initialize memory buffers for each of the device's
|
* Allocate and initialize memory buffers for each of the device's
|
||||||
|
@ -326,6 +341,17 @@ AVRMEM * avr_dup_mem(AVRMEM * m)
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AVRMEM_ALIAS * avr_dup_memalias(AVRMEM_ALIAS * m)
|
||||||
|
{
|
||||||
|
AVRMEM_ALIAS * n;
|
||||||
|
|
||||||
|
n = avr_new_memalias();
|
||||||
|
|
||||||
|
*n = *m;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
void avr_free_mem(AVRMEM * m)
|
void avr_free_mem(AVRMEM * m)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -348,7 +374,36 @@ void avr_free_mem(AVRMEM * m)
|
||||||
free(m);
|
free(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
AVRMEM * avr_locate_mem(AVRPART * p, char * desc)
|
void avr_free_memalias(AVRMEM_ALIAS * m)
|
||||||
|
{
|
||||||
|
free(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
AVRMEM_ALIAS * avr_locate_memalias(AVRPART * p, char * desc)
|
||||||
|
{
|
||||||
|
AVRMEM_ALIAS * m, * match;
|
||||||
|
LNODEID ln;
|
||||||
|
int matches;
|
||||||
|
int l;
|
||||||
|
|
||||||
|
l = strlen(desc);
|
||||||
|
matches = 0;
|
||||||
|
match = NULL;
|
||||||
|
for (ln=lfirst(p->mem_alias); ln; ln=lnext(ln)) {
|
||||||
|
m = ldata(ln);
|
||||||
|
if (strncmp(desc, m->desc, l) == 0) {
|
||||||
|
match = m;
|
||||||
|
matches++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matches == 1)
|
||||||
|
return match;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
AVRMEM * avr_locate_mem_noalias(AVRPART * p, char * desc)
|
||||||
{
|
{
|
||||||
AVRMEM * m, * match;
|
AVRMEM * m, * match;
|
||||||
LNODEID ln;
|
LNODEID ln;
|
||||||
|
@ -373,11 +428,54 @@ AVRMEM * avr_locate_mem(AVRPART * p, char * desc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AVRMEM * avr_locate_mem(AVRPART * p, char * desc)
|
||||||
|
{
|
||||||
|
AVRMEM * m, * match;
|
||||||
|
AVRMEM_ALIAS * alias;
|
||||||
|
LNODEID ln;
|
||||||
|
int matches;
|
||||||
|
int l;
|
||||||
|
|
||||||
|
l = strlen(desc);
|
||||||
|
matches = 0;
|
||||||
|
match = NULL;
|
||||||
|
for (ln=lfirst(p->mem); ln; ln=lnext(ln)) {
|
||||||
|
m = ldata(ln);
|
||||||
|
if (strncmp(desc, m->desc, l) == 0) {
|
||||||
|
match = m;
|
||||||
|
matches++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matches == 1)
|
||||||
|
return match;
|
||||||
|
|
||||||
|
/* not yet found: look for matching alias name */
|
||||||
|
alias = avr_locate_memalias(p, desc);
|
||||||
|
if (alias != NULL)
|
||||||
|
return alias->aliased_mem;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
AVRMEM_ALIAS * avr_find_memalias(AVRPART * p, AVRMEM * m_orig)
|
||||||
|
{
|
||||||
|
AVRMEM_ALIAS * m;
|
||||||
|
LNODEID ln;
|
||||||
|
|
||||||
|
for (ln=lfirst(p->mem_alias); ln; ln=lnext(ln)) {
|
||||||
|
m = ldata(ln);
|
||||||
|
if (m->aliased_mem == m_orig)
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, AVRPART * p,
|
void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, AVRPART * p,
|
||||||
int type, int verbose)
|
int type, int verbose)
|
||||||
{
|
{
|
||||||
static LNODEID ln;
|
|
||||||
static AVRMEM * n;
|
|
||||||
static unsigned int prev_mem_offset, prev_mem_size;
|
static unsigned int prev_mem_offset, prev_mem_size;
|
||||||
int i, j;
|
int i, j;
|
||||||
char * optr;
|
char * optr;
|
||||||
|
@ -398,25 +496,14 @@ void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, AVRPART * p,
|
||||||
prefix, prefix, prefix);
|
prefix, prefix, prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the next memory section, and stop before going out of band
|
|
||||||
if (ln == NULL)
|
|
||||||
ln = lnext(lfirst(p->mem));
|
|
||||||
else
|
|
||||||
ln = lnext(ln);
|
|
||||||
if (ln != NULL)
|
|
||||||
n = ldata(ln);
|
|
||||||
|
|
||||||
// Only print memory section if the previous section printed isn't identical
|
// 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)) {
|
if(prev_mem_offset != m->offset || prev_mem_size != m->size || (strcmp(p->family_id, "") == 0)) {
|
||||||
prev_mem_offset = m->offset;
|
prev_mem_offset = m->offset;
|
||||||
prev_mem_size = m->size;
|
prev_mem_size = m->size;
|
||||||
|
AVRMEM_ALIAS *ap = avr_find_memalias(p, m);
|
||||||
/* Show alias if the current and the next memory section has the same offset
|
/* 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 */
|
and size, we're not out of band and a family_id is present */
|
||||||
char * mem_desc_alias = m->offset == n->offset && \
|
char * mem_desc_alias = ap? ap->desc: "";
|
||||||
m->size == n->size && \
|
|
||||||
ln != NULL && \
|
|
||||||
strcmp(p->family_id, "") != 0 ?
|
|
||||||
n->desc : "";
|
|
||||||
fprintf(f,
|
fprintf(f,
|
||||||
"%s%-11s %-8s %4d %5d %5d %4d %-6s %6d %4d %6d %5d %5d 0x%02x 0x%02x\n",
|
"%s%-11s %-8s %4d %5d %5d %4d %-6s %6d %4d %6d %5d %5d 0x%02x 0x%02x\n",
|
||||||
prefix,
|
prefix,
|
||||||
|
@ -488,6 +575,7 @@ AVRPART * avr_new_part(void)
|
||||||
p->ocdrev = -1;
|
p->ocdrev = -1;
|
||||||
|
|
||||||
p->mem = lcreat(NULL, 0);
|
p->mem = lcreat(NULL, 0);
|
||||||
|
p->mem_alias = lcreat(NULL, 0);
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
@ -496,19 +584,35 @@ AVRPART * avr_new_part(void)
|
||||||
AVRPART * avr_dup_part(AVRPART * d)
|
AVRPART * avr_dup_part(AVRPART * d)
|
||||||
{
|
{
|
||||||
AVRPART * p;
|
AVRPART * p;
|
||||||
LISTID save;
|
LISTID save, save2;
|
||||||
LNODEID ln;
|
LNODEID ln, ln2;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
p = avr_new_part();
|
p = avr_new_part();
|
||||||
save = p->mem;
|
save = p->mem;
|
||||||
|
save2 = p->mem_alias;
|
||||||
|
|
||||||
*p = *d;
|
*p = *d;
|
||||||
|
|
||||||
p->mem = save;
|
p->mem = save;
|
||||||
|
p->mem_alias = save2;
|
||||||
|
|
||||||
for (ln=lfirst(d->mem); ln; ln=lnext(ln)) {
|
for (ln=lfirst(d->mem); ln; ln=lnext(ln)) {
|
||||||
ladd(p->mem, avr_dup_mem(ldata(ln)));
|
AVRMEM *m = ldata(ln);
|
||||||
|
AVRMEM *m2 = avr_dup_mem(m);
|
||||||
|
ladd(p->mem, m2);
|
||||||
|
// see if there is any alias for it
|
||||||
|
for (ln2=lfirst(d->mem_alias); ln2; ln2=lnext(ln2)) {
|
||||||
|
AVRMEM_ALIAS *a = ldata(ln2);
|
||||||
|
if (a->aliased_mem == m) {
|
||||||
|
// yes, duplicate it
|
||||||
|
AVRMEM_ALIAS *a2 = avr_dup_memalias(a);
|
||||||
|
// ... adjust the pointer ...
|
||||||
|
a2->aliased_mem = m2;
|
||||||
|
// ... and add to new list
|
||||||
|
ladd(p->mem_alias, a2);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < AVR_OP_MAX; i++) {
|
for (i = 0; i < AVR_OP_MAX; i++) {
|
||||||
|
@ -523,6 +627,8 @@ void avr_free_part(AVRPART * d)
|
||||||
int i;
|
int i;
|
||||||
ldestroy_cb(d->mem, (void(*)(void *))avr_free_mem);
|
ldestroy_cb(d->mem, (void(*)(void *))avr_free_mem);
|
||||||
d->mem = NULL;
|
d->mem = NULL;
|
||||||
|
ldestroy_cb(d->mem_alias, (void(*)(void *))avr_free_memalias);
|
||||||
|
d->mem_alias = NULL;
|
||||||
for(i=0;i<sizeof(d->op)/sizeof(d->op[0]);i++)
|
for(i=0;i<sizeof(d->op)/sizeof(d->op[0]);i++)
|
||||||
{
|
{
|
||||||
if (d->op[i] != NULL)
|
if (d->op[i] != NULL)
|
||||||
|
|
|
@ -47,6 +47,7 @@ AVRPART * current_part;
|
||||||
AVRMEM * current_mem;
|
AVRMEM * current_mem;
|
||||||
LISTID part_list;
|
LISTID part_list;
|
||||||
LISTID programmers;
|
LISTID programmers;
|
||||||
|
bool is_alias;
|
||||||
|
|
||||||
int lineno;
|
int lineno;
|
||||||
const char * infile;
|
const char * infile;
|
||||||
|
@ -72,6 +73,7 @@ int init_config(void)
|
||||||
current_mem = NULL;
|
current_mem = NULL;
|
||||||
part_list = lcreat(NULL, 0);
|
part_list = lcreat(NULL, 0);
|
||||||
programmers = lcreat(NULL, 0);
|
programmers = lcreat(NULL, 0);
|
||||||
|
is_alias = false;
|
||||||
|
|
||||||
lineno = 1;
|
lineno = 1;
|
||||||
infile = NULL;
|
infile = NULL;
|
||||||
|
|
|
@ -54,6 +54,7 @@ extern int lineno;
|
||||||
extern const char * infile;
|
extern const char * infile;
|
||||||
extern LISTID string_list;
|
extern LISTID string_list;
|
||||||
extern LISTID number_list;
|
extern LISTID number_list;
|
||||||
|
extern bool is_alias; // current entry is alias
|
||||||
|
|
||||||
|
|
||||||
#if !defined(HAS_YYSTYPE)
|
#if !defined(HAS_YYSTYPE)
|
||||||
|
|
|
@ -68,6 +68,7 @@ static int pin_name;
|
||||||
%token K_PAGE_SIZE
|
%token K_PAGE_SIZE
|
||||||
%token K_PAGED
|
%token K_PAGED
|
||||||
|
|
||||||
|
%token K_ALIAS
|
||||||
%token K_BAUDRATE
|
%token K_BAUDRATE
|
||||||
%token K_BS2
|
%token K_BS2
|
||||||
%token K_BUFF
|
%token K_BUFF
|
||||||
|
@ -1238,13 +1239,24 @@ part_parm :
|
||||||
mem_specs
|
mem_specs
|
||||||
{
|
{
|
||||||
AVRMEM * existing_mem;
|
AVRMEM * existing_mem;
|
||||||
|
AVRMEM_ALIAS * existing_alias;
|
||||||
|
|
||||||
existing_mem = avr_locate_mem(current_part, current_mem->desc);
|
existing_mem = avr_locate_mem_noalias(current_part, current_mem->desc);
|
||||||
if (existing_mem != NULL) {
|
if (existing_mem != NULL) {
|
||||||
lrmv_d(current_part->mem, existing_mem);
|
lrmv_d(current_part->mem, existing_mem);
|
||||||
avr_free_mem(existing_mem);
|
avr_free_mem(existing_mem);
|
||||||
}
|
}
|
||||||
ladd(current_part->mem, current_mem);
|
existing_alias = avr_locate_memalias(current_part, current_mem->desc);
|
||||||
|
if (existing_alias != NULL) {
|
||||||
|
lrmv_d(current_part->mem_alias, existing_alias);
|
||||||
|
avr_free_memalias(existing_alias);
|
||||||
|
}
|
||||||
|
if (is_alias) {
|
||||||
|
avr_free_mem(current_mem); // alias mem has been already entered below
|
||||||
|
is_alias = false;
|
||||||
|
} else {
|
||||||
|
ladd(current_part->mem, current_mem);
|
||||||
|
}
|
||||||
current_mem = NULL;
|
current_mem = NULL;
|
||||||
} |
|
} |
|
||||||
|
|
||||||
|
@ -1281,6 +1293,7 @@ yesno :
|
||||||
|
|
||||||
mem_specs :
|
mem_specs :
|
||||||
mem_spec TKN_SEMI |
|
mem_spec TKN_SEMI |
|
||||||
|
mem_alias TKN_SEMI |
|
||||||
mem_specs mem_spec TKN_SEMI
|
mem_specs mem_spec TKN_SEMI
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -1410,6 +1423,44 @@ mem_spec :
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
mem_alias :
|
||||||
|
K_ALIAS TKN_STRING
|
||||||
|
{
|
||||||
|
AVRMEM * existing_mem;
|
||||||
|
|
||||||
|
existing_mem = avr_locate_mem(current_part, $2->value.string);
|
||||||
|
if (existing_mem == NULL) {
|
||||||
|
yyerror("%s alias to non-existent memory %s",
|
||||||
|
current_mem->desc, $2->value.string);
|
||||||
|
free_token($2);
|
||||||
|
YYABORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this alias does already exist, drop the old one
|
||||||
|
AVRMEM_ALIAS * alias = avr_locate_memalias(current_part, current_mem->desc);
|
||||||
|
if (alias) {
|
||||||
|
lrmv_d(current_part->mem_alias, alias);
|
||||||
|
avr_free_memalias(alias);
|
||||||
|
}
|
||||||
|
// NB: we do *not* check whether any non-alias region of the
|
||||||
|
// same name does already exist, as that one could be pointed to
|
||||||
|
// by an(other) alias as well. If we destroyed it, the alias
|
||||||
|
// pointer would get stale. In case someone defines the same
|
||||||
|
// name both as a regular memory as well as an alias, the
|
||||||
|
// regular one will always be found first by avr_locate_mem().
|
||||||
|
|
||||||
|
is_alias = true;
|
||||||
|
alias = avr_new_memalias();
|
||||||
|
|
||||||
|
// alias->desc and current_mem->desc have the same length
|
||||||
|
// definition, thus no need to check for length here
|
||||||
|
strcpy(alias->desc, current_mem->desc);
|
||||||
|
alias->aliased_mem = existing_mem;
|
||||||
|
ladd(current_part->mem_alias, alias);
|
||||||
|
|
||||||
|
free_token($2);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
|
|
|
@ -117,6 +117,7 @@ SIGN [+-]
|
||||||
<strng>\n { yyerror("unterminated character constant");
|
<strng>\n { yyerror("unterminated character constant");
|
||||||
return YYERRCODE; }
|
return YYERRCODE; }
|
||||||
|
|
||||||
|
alias { yylval=NULL; return K_ALIAS; }
|
||||||
allowfullpagebitstream { yylval=NULL; return K_ALLOWFULLPAGEBITSTREAM; }
|
allowfullpagebitstream { yylval=NULL; return K_ALLOWFULLPAGEBITSTREAM; }
|
||||||
avr910_devcode { yylval=NULL; return K_AVR910_DEVCODE; }
|
avr910_devcode { yylval=NULL; return K_AVR910_DEVCODE; }
|
||||||
bank_size { yylval=NULL; return K_PAGE_SIZE; }
|
bank_size { yylval=NULL; return K_PAGE_SIZE; }
|
||||||
|
|
|
@ -261,6 +261,7 @@ typedef struct avrpart {
|
||||||
OPCODE * op[AVR_OP_MAX]; /* opcodes */
|
OPCODE * op[AVR_OP_MAX]; /* opcodes */
|
||||||
|
|
||||||
LISTID mem; /* avr memory definitions */
|
LISTID mem; /* avr memory definitions */
|
||||||
|
LISTID mem_alias; /* memory alias definitions */
|
||||||
char config_file[PATH_MAX]; /* config file where defined */
|
char config_file[PATH_MAX]; /* config file where defined */
|
||||||
int lineno; /* config file line number */
|
int lineno; /* config file line number */
|
||||||
} AVRPART;
|
} AVRPART;
|
||||||
|
@ -292,6 +293,11 @@ typedef struct avrmem {
|
||||||
OPCODE * op[AVR_OP_MAX]; /* opcodes */
|
OPCODE * op[AVR_OP_MAX]; /* opcodes */
|
||||||
} AVRMEM;
|
} AVRMEM;
|
||||||
|
|
||||||
|
typedef struct avrmem_alias {
|
||||||
|
char desc[AVR_MEMDESCLEN]; /* alias name ("syscfg0" etc.) */
|
||||||
|
AVRMEM *aliased_mem;
|
||||||
|
} AVRMEM_ALIAS;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -307,10 +313,15 @@ int avr_get_output_index(OPCODE * op);
|
||||||
|
|
||||||
/* Functions for AVRMEM structures */
|
/* Functions for AVRMEM structures */
|
||||||
AVRMEM * avr_new_memtype(void);
|
AVRMEM * avr_new_memtype(void);
|
||||||
|
AVRMEM_ALIAS * avr_new_memalias(void);
|
||||||
int avr_initmem(AVRPART * p);
|
int avr_initmem(AVRPART * p);
|
||||||
AVRMEM * avr_dup_mem(AVRMEM * m);
|
AVRMEM * avr_dup_mem(AVRMEM * m);
|
||||||
void avr_free_mem(AVRMEM * m);
|
void avr_free_mem(AVRMEM * m);
|
||||||
|
void avr_free_memalias(AVRMEM_ALIAS * m);
|
||||||
AVRMEM * avr_locate_mem(AVRPART * p, char * desc);
|
AVRMEM * avr_locate_mem(AVRPART * p, char * desc);
|
||||||
|
AVRMEM * avr_locate_mem_noalias(AVRPART * p, char * desc);
|
||||||
|
AVRMEM_ALIAS * avr_locate_memalias(AVRPART * p, char * desc);
|
||||||
|
AVRMEM_ALIAS * avr_find_memalias(AVRPART * p, AVRMEM * m_orig);
|
||||||
void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, AVRPART * p,
|
void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, AVRPART * p,
|
||||||
int type, int verbose);
|
int type, int verbose);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue