bug #34302: Feature request : device configuration with parent classes

* config_gram.y: if memory section is overwritten old entry is removed
        
(not in original patch)
* config_gram.y: if programmer or part is defined twice, a warning is
  output and the first instance is removed
        
General cleanup and free functions, so valgrind does not report any lost
blocks at program end.
* avrpart.[hc]: added avr_free_(opcode|mem|part) functions
* pgm.[hc]: added pgm_free function
* update.[hc]: added free_update functions
* config.[hc]: added cleanup_config function, use yylex_destroy to reset
  the lexer after usage. (So it can be reused.)
* main.c: add cleanup_main function which is called by atexit() (This 
  frees all lists so that at program exit only really lost memory is 
  reported by valgrind.)
* usbasp.c: added libusb_free_device_list() and libusb_exit() calls to
  avoid lost memory
* buspirate.c: moved memory allocation from initpgm to setup and added 
  free in teardown
* configure.ac: add definition of HAVE_YYLEX_DESTROY if $LEX is flex.
* Makefile.am: added . in front of SUBDIRS to build avrdude before trying
  to use it for creating the part list for the docs.



git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk@1041 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
Rene Liebscher 2012-01-17 20:56:37 +00:00
parent fe7be6301e
commit 459aa147e7
15 changed files with 203 additions and 18 deletions

View File

@ -1,3 +1,30 @@
2012-01-17 Rene Liebscher <R.Liebscher@gmx.de>
bug #34302: Feature request : device configuration with parent classes
* config_gram.y: if memory section is overwritten old entry is removed
(not in original patch)
* config_gram.y: if programmer or part is defined twice, a warning is
output and the first instance is removed
General cleanup and free functions, so valgrind does not report any lost
blocks at program end.
* avrpart.[hc]: added avr_free_(opcode|mem|part) functions
* pgm.[hc]: added pgm_free function
* update.[hc]: added free_update functions
* config.[hc]: added cleanup_config function, use yylex_destroy to reset
the lexer after usage. (So it can be reused.)
* main.c: add cleanup_main function which is called by atexit() (This
frees all lists so that at program exit only really lost memory is
reported by valgrind.)
* usbasp.c: added libusb_free_device_list() and libusb_exit() calls to
avoid lost memory
* buspirate.c: moved memory allocation from initpgm to setup and added
free in teardown
* configure.ac: add definition of HAVE_YYLEX_DESTROY if $LEX is flex.
* Makefile.am: added . in front of SUBDIRS to build avrdude before trying
to use it for creating the part list for the docs.
2012-01-17 Rene Liebscher <R.Liebscher@gmx.de> 2012-01-17 Rene Liebscher <R.Liebscher@gmx.de>
* usbasp.c: USB vid/pid/vendor/product from config file are used, for * usbasp.c: USB vid/pid/vendor/product from config file are used, for

View File

@ -44,7 +44,10 @@ BUILT_SOURCES = $(CLEANFILES)
#SUBDIRS = doc @WINDOWS_DIRS@ #SUBDIRS = doc @WINDOWS_DIRS@
#DIST_SUBDIRS = doc windows #DIST_SUBDIRS = doc windows
SUBDIRS = @SUBDIRS_AC@ # . lets build this directory before the following in SUBDIRS
SUBDIRS = .
# doc comes here, and we want to use the built avrdude to generate the parts list
SUBDIRS += @SUBDIRS_AC@
SUBDIRS += @WINDOWS_DIRS@ SUBDIRS += @WINDOWS_DIRS@
DIST_SUBDIRS = @DIST_SUBDIRS_AC@ DIST_SUBDIRS = @DIST_SUBDIRS_AC@

View File

@ -67,6 +67,10 @@ static OPCODE * avr_dup_opcode(OPCODE * op)
return m; return m;
} }
void avr_free_opcode(OPCODE * op)
{
free(op);
}
/* /*
* avr_set_bits() * avr_set_bits()
@ -303,6 +307,27 @@ AVRMEM * avr_dup_mem(AVRMEM * m)
return n; return n;
} }
void avr_free_mem(AVRMEM * m)
{
int i;
if (m->buf != NULL) {
free(m->buf);
m->buf = NULL;
}
if (m->tags != NULL) {
free(m->tags);
m->tags = NULL;
}
for(i=0;i<sizeof(m->op)/sizeof(m->op[0]);i++)
{
if (m->op[i] != NULL)
{
avr_free_opcode(m->op[i]);
m->op[i] = NULL;
}
}
free(m);
}
AVRMEM * avr_locate_mem(AVRPART * p, char * desc) AVRMEM * avr_locate_mem(AVRPART * p, char * desc)
{ {
@ -447,6 +472,21 @@ AVRPART * avr_dup_part(AVRPART * d)
return p; return p;
} }
void avr_free_part(AVRPART * d)
{
int i;
ldestroy_cb(d->mem,avr_free_mem);
d->mem = NULL;
for(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;
}
}
free(d);
}
AVRPART * locate_part(LISTID parts, char * partdesc) AVRPART * locate_part(LISTID parts, char * partdesc)
{ {

View File

@ -198,6 +198,7 @@ extern "C" {
/* Functions for OPCODE structures */ /* Functions for OPCODE structures */
OPCODE * avr_new_opcode(void); OPCODE * avr_new_opcode(void);
void avr_free_opcode(OPCODE * op);
int avr_set_bits(OPCODE * op, unsigned char * cmd); int avr_set_bits(OPCODE * op, unsigned char * cmd);
int avr_set_addr(OPCODE * op, unsigned char * cmd, unsigned long addr); int avr_set_addr(OPCODE * op, unsigned char * cmd, unsigned long addr);
int avr_set_input(OPCODE * op, unsigned char * cmd, unsigned char data); int avr_set_input(OPCODE * op, unsigned char * cmd, unsigned char data);
@ -207,6 +208,7 @@ int avr_get_output(OPCODE * op, unsigned char * res, unsigned char * data);
AVRMEM * avr_new_memtype(void); AVRMEM * avr_new_memtype(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);
AVRMEM * avr_locate_mem(AVRPART * p, char * desc); AVRMEM * avr_locate_mem(AVRPART * p, char * desc);
void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, int type, void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, int type,
int verbose); int verbose);
@ -214,6 +216,7 @@ void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, int type,
/* Functions for AVRPART structures */ /* Functions for AVRPART structures */
AVRPART * avr_new_part(void); AVRPART * avr_new_part(void);
AVRPART * avr_dup_part(AVRPART * d); AVRPART * avr_dup_part(AVRPART * d);
void avr_free_part(AVRPART * d);
AVRPART * locate_part(LISTID parts, char * partdesc); AVRPART * locate_part(LISTID parts, char * partdesc);
AVRPART * locate_part_by_avr910_devcode(LISTID parts, int devcode); AVRPART * locate_part_by_avr910_devcode(LISTID parts, int devcode);
void avr_display(FILE * f, AVRPART * p, const char * prefix, int verbose); void avr_display(FILE * f, AVRPART * p, const char * prefix, int verbose);

View File

@ -760,6 +760,22 @@ static int buspirate_chip_erase(struct programmer_t *pgm, AVRPART * p)
return 0; return 0;
} }
/* Interface - management */
static void buspirate_setup(struct programmer_t *pgm)
{
/* Allocate private data */
if ((pgm->cookie = calloc(1, sizeof(struct pdata))) == 0) {
fprintf(stderr, "%s: buspirate_initpgm(): Out of memory allocating private data\n",
progname);
exit(1);
}
}
static void buspirate_teardown(struct programmer_t *pgm)
{
free(pgm->cookie);
}
void buspirate_initpgm(struct programmer_t *pgm) void buspirate_initpgm(struct programmer_t *pgm)
{ {
strcpy(pgm->type, "BusPirate"); strcpy(pgm->type, "BusPirate");
@ -785,11 +801,7 @@ void buspirate_initpgm(struct programmer_t *pgm)
/* Support functions */ /* Support functions */
pgm->parseextparams = buspirate_parseextparms; pgm->parseextparams = buspirate_parseextparms;
/* Allocate private data */ pgm->setup = buspirate_setup;
if ((pgm->cookie = calloc(1, sizeof(struct pdata))) == 0) { pgm->teardown = buspirate_teardown;
fprintf(stderr, "%s: buspirate_initpgm(): Out of memory allocating private data\n",
progname);
exit(1);
}
} }

View File

@ -55,6 +55,13 @@ extern char * yytext;
#define DEBUG 0 #define DEBUG 0
void cleanup_config(void)
{
ldestroy_cb(part_list,avr_free_part);
ldestroy_cb(programmers,pgm_free);
ldestroy_cb(string_list,free_token);
ldestroy_cb(number_list,free_token);
}
int init_config(void) int init_config(void)
{ {
@ -62,7 +69,7 @@ int init_config(void)
number_list = lcreat(NULL, 0); number_list = lcreat(NULL, 0);
current_prog = NULL; current_prog = NULL;
current_part = NULL; current_part = NULL;
current_mem = 0; current_mem = NULL;
part_list = lcreat(NULL, 0); part_list = lcreat(NULL, 0);
programmers = lcreat(NULL, 0); programmers = lcreat(NULL, 0);
@ -301,6 +308,11 @@ int read_config(const char * file)
yyparse(); yyparse();
#ifdef HAVE_YYLEX_DESTROY
/* reset lexer and free any allocated memory */
yylex_destroy();
#endif
fclose(f); fclose(f);
return 0; return 0;

View File

@ -78,6 +78,8 @@ int yyparse(void);
int init_config(void); int init_config(void);
void cleanup_config(void);
TOKEN * new_token(int primary); TOKEN * new_token(int primary);
void free_token(TOKEN * tkn); void free_token(TOKEN * tkn);

View File

@ -290,6 +290,8 @@ def :
prog_def : prog_def :
prog_decl prog_parms prog_decl prog_parms
{ {
PROGRAMMER * existing_prog;
char * id;
if (lsize(current_prog->id) == 0) { if (lsize(current_prog->id) == 0) {
fprintf(stderr, fprintf(stderr,
"%s: error at %s:%d: required parameter id not specified\n", "%s: error at %s:%d: required parameter id not specified\n",
@ -301,6 +303,16 @@ prog_def :
progname, infile, lineno); progname, infile, lineno);
exit(1); exit(1);
} }
id = ldata(lfirst(current_prog->id));
existing_prog = locate_programmer(programmers, id);
if (existing_prog) {
fprintf(stderr, "%s: warning at %s:%d: programmer %s overwrites "
"previous definition %s:%d.\n",
progname, infile, current_prog->lineno,
id, existing_prog->config_file, existing_prog->lineno);
lrmv_d(programmers, existing_prog);
pgm_free(existing_prog);
}
PUSH(programmers, current_prog); PUSH(programmers, current_prog);
current_prog = NULL; current_prog = NULL;
} }
@ -321,6 +333,7 @@ part_def :
{ {
LNODEID ln; LNODEID ln;
AVRMEM * m; AVRMEM * m;
AVRPART * existing_part;
if (current_part->id[0] == 0) { if (current_part->id[0] == 0) {
fprintf(stderr, fprintf(stderr,
@ -366,6 +379,15 @@ part_def :
} }
} }
existing_part = locate_part(part_list, current_part->id);
if (existing_part) {
fprintf(stderr, "%s: warning at %s:%d: part %s overwrites "
"previous definition %s:%d.\n",
progname, infile, current_part->lineno, current_part->id,
existing_part->config_file, existing_part->lineno);
lrmv_d(part_list, existing_part);
avr_free_part(existing_part);
}
PUSH(part_list, current_part); PUSH(part_list, current_part);
current_part = NULL; current_part = NULL;
} }
@ -1146,6 +1168,13 @@ part_parm :
} }
mem_specs mem_specs
{ {
AVRMEM * existing_mem;
existing_mem = avr_locate_mem(current_part, current_mem->desc);
if (existing_mem != NULL) {
lrmv_d(current_part->mem, existing_mem);
avr_free_mem(existing_mem);
}
ladd(current_part->mem, current_mem); ladd(current_part->mem, current_mem);
current_mem = NULL; current_mem = NULL;
} | } |
@ -1162,7 +1191,7 @@ part_parm :
/*fprintf(stderr, /*fprintf(stderr,
"%s: warning at %s:%d: operation redefined\n", "%s: warning at %s:%d: operation redefined\n",
progname, infile, lineno);*/ progname, infile, lineno);*/
free(current_part->op[opnum]); avr_free_opcode(current_part->op[opnum]);
} }
current_part->op[opnum] = op; current_part->op[opnum] = op;
@ -1289,7 +1318,7 @@ mem_spec :
/*fprintf(stderr, /*fprintf(stderr,
"%s: warning at %s:%d: operation redefined\n", "%s: warning at %s:%d: operation redefined\n",
progname, infile, lineno);*/ progname, infile, lineno);*/
free(current_mem->op[opnum]); avr_free_opcode(current_mem->op[opnum]);
} }
current_mem->op[opnum] = op; current_mem->op[opnum] = op;

View File

@ -40,6 +40,12 @@ AC_PROG_INSTALL
AC_PROG_YACC AC_PROG_YACC
AC_PROG_LEX AC_PROG_LEX
AC_PROG_RANLIB AC_PROG_RANLIB
AH_TEMPLATE([HAVE_YYLEX_DESTROY],
[Define if lex/flex has yylex_destroy])
# flex should have this
if test "x$LEX" == xflex; then
AC_DEFINE([HAVE_YYLEX_DESTROY])
fi
dnl Makefile.am:77: compiling `config_gram.c' with per-target flags requires `AM_PROG_CC_C_O' in `configure.ac' dnl Makefile.am:77: compiling `config_gram.c' with per-target flags requires `AM_PROG_CC_C_O' in `configure.ac'
AM_PROG_CC_C_O AM_PROG_CC_C_O

View File

@ -71,11 +71,11 @@ struct list_walk_cookie
const char *prefix; const char *prefix;
}; };
static LISTID updates; static LISTID updates = NULL;
static LISTID extended_params; static LISTID extended_params = NULL;
static LISTID additional_config_files; static LISTID additional_config_files = NULL;
static PROGRAMMER * pgm; static PROGRAMMER * pgm;
@ -254,6 +254,24 @@ static void exithook(void)
pgm->teardown(pgm); pgm->teardown(pgm);
} }
static void cleanup_main(void)
{
if (updates) {
ldestroy_cb(updates,free_update);
updates = NULL;
}
if (extended_params) {
ldestroy(extended_params);
extended_params = NULL;
}
if (additional_config_files) {
ldestroy(additional_config_files);
additional_config_files = NULL;
}
cleanup_config();
}
/* /*
* main routine * main routine
*/ */
@ -332,6 +350,8 @@ int main(int argc, char * argv [])
init_config(); init_config();
atexit(cleanup_main);
updates = lcreat(NULL, 0); updates = lcreat(NULL, 0);
if (updates == NULL) { if (updates == NULL) {
fprintf(stderr, "%s: cannot initialize updater list\n", progname); fprintf(stderr, "%s: cannot initialize updater list\n", progname);

View File

@ -135,6 +135,17 @@ PROGRAMMER * pgm_new(void)
return pgm; return pgm;
} }
void pgm_free(PROGRAMMER * const p)
{
ldestroy_cb(p->id,free);
p->id = NULL;
/* this is done by pgm_teardown, but usually cookie is not set to NULL */
/* if (p->cookie !=NULL) {
free(p->cookie);
p->cookie = NULL;
}*/
free(p);
}
static void pgm_default(void) static void pgm_default(void)
{ {

View File

@ -131,6 +131,7 @@ extern "C" {
#endif #endif
PROGRAMMER * pgm_new(void); PROGRAMMER * pgm_new(void);
void pgm_free(PROGRAMMER * const p);
void programmer_display(PROGRAMMER * pgm, const char * p); void programmer_display(PROGRAMMER * pgm, const char * p);
PROGRAMMER * locate_programmer(LISTID programmers, const char * configid); PROGRAMMER * locate_programmer(LISTID programmers, const char * configid);

View File

@ -200,6 +200,22 @@ UPDATE * new_update(int op, char * memtype, int filefmt, char * filename)
return u; return u;
} }
void free_update(UPDATE * u)
{
if (u != NULL) {
if(u->memtype != NULL) {
free(u->memtype);
u->memtype = NULL;
}
if(u->filename != NULL) {
free(u->filename);
u->filename = NULL;
}
free(u);
}
}
int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, int nowrite) int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, int nowrite)
{ {
struct avrpart * v; struct avrpart * v;

View File

@ -45,6 +45,7 @@ extern UPDATE * parse_op(char * s);
extern UPDATE * dup_update(UPDATE * upd); extern UPDATE * dup_update(UPDATE * upd);
extern UPDATE * new_update(int op, char * memtype, int filefmt, extern UPDATE * new_update(int op, char * memtype, int filefmt,
char * filename); char * filename);
extern void free_update(UPDATE * upd);
extern int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, extern int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd,
int nowrite); int nowrite);

View File

@ -305,6 +305,7 @@ static int usbOpenDevice(libusb_device_handle **device, int vendor,
handle = NULL; handle = NULL;
} }
} }
libusb_free_device_list(dev_list,1);
if (handle != NULL){ if (handle != NULL){
errorCode = 0; errorCode = 0;
*device = handle; *device = handle;
@ -401,11 +402,7 @@ static int didUsbInit = 0;
/* Interface - prog. */ /* Interface - prog. */
static int usbasp_open(PROGRAMMER * pgm, char * port) static int usbasp_open(PROGRAMMER * pgm, char * port)
{ {
#ifdef USE_LIBUSB_1_0 /* usb_init will be done in usbOpenDevice */
libusb_init(&ctx);
#else
usb_init();
#endif
if (usbOpenDevice(&PDATA(pgm)->usbhandle, pgm->usbvid, pgm->usbvendor, if (usbOpenDevice(&PDATA(pgm)->usbhandle, pgm->usbvid, pgm->usbvendor,
pgm->usbpid, pgm->usbproduct) != 0) { pgm->usbpid, pgm->usbproduct) != 0) {
/* try alternatives */ /* try alternatives */
@ -474,6 +471,11 @@ static void usbasp_close(PROGRAMMER * pgm)
usb_close(PDATA(pgm)->usbhandle); usb_close(PDATA(pgm)->usbhandle);
#endif #endif
} }
#ifdef USE_LIBUSB_1_0
libusb_exit(ctx);
#else
/* nothing for usb 0.1 ? */
#endif
} }