From 0a84dcee24c9b9588396dc92ffdf02f7b6322198 Mon Sep 17 00:00:00 2001 From: Rene Liebscher Date: Tue, 17 Jan 2012 20:56:37 +0000 Subject: [PATCH] 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/avrdude@1041 81a1dc3b-b13d-400b-aceb-764788c761c2 --- ChangeLog | 27 +++++++++++++++++++++++++++ Makefile.am | 5 ++++- avrpart.c | 40 ++++++++++++++++++++++++++++++++++++++++ avrpart.h | 3 +++ buspirate.c | 24 ++++++++++++++++++------ config.c | 14 +++++++++++++- config.h | 2 ++ config_gram.y | 33 +++++++++++++++++++++++++++++++-- configure.ac | 6 ++++++ main.c | 26 +++++++++++++++++++++++--- pgm.c | 11 +++++++++++ pgm.h | 1 + update.c | 16 ++++++++++++++++ update.h | 1 + usbasp.c | 12 +++++++----- 15 files changed, 203 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5851ad22..7e748b1a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,30 @@ +2012-01-17 Rene Liebscher + + 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 * usbasp.c: USB vid/pid/vendor/product from config file are used, for diff --git a/Makefile.am b/Makefile.am index 49a3182b..343a56dc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -44,7 +44,10 @@ BUILT_SOURCES = $(CLEANFILES) #SUBDIRS = doc @WINDOWS_DIRS@ #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@ DIST_SUBDIRS = @DIST_SUBDIRS_AC@ diff --git a/avrpart.c b/avrpart.c index 0dba3f64..280721be 100644 --- a/avrpart.c +++ b/avrpart.c @@ -67,6 +67,10 @@ static OPCODE * avr_dup_opcode(OPCODE * op) return m; } +void avr_free_opcode(OPCODE * op) +{ + free(op); +} /* * avr_set_bits() @@ -303,6 +307,27 @@ AVRMEM * avr_dup_mem(AVRMEM * m) 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;iop)/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) { @@ -447,6 +472,21 @@ AVRPART * avr_dup_part(AVRPART * d) return p; } +void avr_free_part(AVRPART * d) +{ +int i; + ldestroy_cb(d->mem,avr_free_mem); + d->mem = NULL; + for(i=0;iop)/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) { diff --git a/avrpart.h b/avrpart.h index 70bdb085..90a6f267 100644 --- a/avrpart.h +++ b/avrpart.h @@ -198,6 +198,7 @@ extern "C" { /* Functions for OPCODE structures */ OPCODE * avr_new_opcode(void); +void avr_free_opcode(OPCODE * op); int avr_set_bits(OPCODE * op, unsigned char * cmd); int avr_set_addr(OPCODE * op, unsigned char * cmd, unsigned long addr); 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); int avr_initmem(AVRPART * p); AVRMEM * avr_dup_mem(AVRMEM * m); +void avr_free_mem(AVRMEM * m); AVRMEM * avr_locate_mem(AVRPART * p, char * desc); void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, int type, int verbose); @@ -214,6 +216,7 @@ void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, int type, /* Functions for AVRPART structures */ AVRPART * avr_new_part(void); AVRPART * avr_dup_part(AVRPART * d); +void avr_free_part(AVRPART * d); AVRPART * locate_part(LISTID parts, char * partdesc); AVRPART * locate_part_by_avr910_devcode(LISTID parts, int devcode); void avr_display(FILE * f, AVRPART * p, const char * prefix, int verbose); diff --git a/buspirate.c b/buspirate.c index d2034aab..090b54c8 100644 --- a/buspirate.c +++ b/buspirate.c @@ -760,6 +760,22 @@ static int buspirate_chip_erase(struct programmer_t *pgm, AVRPART * p) 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) { strcpy(pgm->type, "BusPirate"); @@ -785,11 +801,7 @@ void buspirate_initpgm(struct programmer_t *pgm) /* Support functions */ pgm->parseextparams = buspirate_parseextparms; - /* 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); - } + pgm->setup = buspirate_setup; + pgm->teardown = buspirate_teardown; } diff --git a/config.c b/config.c index 6f0b571d..8a13befb 100644 --- a/config.c +++ b/config.c @@ -55,6 +55,13 @@ extern char * yytext; #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) { @@ -62,7 +69,7 @@ int init_config(void) number_list = lcreat(NULL, 0); current_prog = NULL; current_part = NULL; - current_mem = 0; + current_mem = NULL; part_list = lcreat(NULL, 0); programmers = lcreat(NULL, 0); @@ -301,6 +308,11 @@ int read_config(const char * file) yyparse(); +#ifdef HAVE_YYLEX_DESTROY + /* reset lexer and free any allocated memory */ + yylex_destroy(); +#endif + fclose(f); return 0; diff --git a/config.h b/config.h index 02355795..835e9c3b 100644 --- a/config.h +++ b/config.h @@ -78,6 +78,8 @@ int yyparse(void); int init_config(void); +void cleanup_config(void); + TOKEN * new_token(int primary); void free_token(TOKEN * tkn); diff --git a/config_gram.y b/config_gram.y index 64eb2750..45f0ce30 100644 --- a/config_gram.y +++ b/config_gram.y @@ -290,6 +290,8 @@ def : prog_def : prog_decl prog_parms { + PROGRAMMER * existing_prog; + char * id; if (lsize(current_prog->id) == 0) { fprintf(stderr, "%s: error at %s:%d: required parameter id not specified\n", @@ -301,6 +303,16 @@ prog_def : progname, infile, lineno); 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); current_prog = NULL; } @@ -321,6 +333,7 @@ part_def : { LNODEID ln; AVRMEM * m; + AVRPART * existing_part; if (current_part->id[0] == 0) { 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); current_part = NULL; } @@ -1146,6 +1168,13 @@ part_parm : } 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); current_mem = NULL; } | @@ -1162,7 +1191,7 @@ part_parm : /*fprintf(stderr, "%s: warning at %s:%d: operation redefined\n", progname, infile, lineno);*/ - free(current_part->op[opnum]); + avr_free_opcode(current_part->op[opnum]); } current_part->op[opnum] = op; @@ -1289,7 +1318,7 @@ mem_spec : /*fprintf(stderr, "%s: warning at %s:%d: operation redefined\n", progname, infile, lineno);*/ - free(current_mem->op[opnum]); + avr_free_opcode(current_mem->op[opnum]); } current_mem->op[opnum] = op; diff --git a/configure.ac b/configure.ac index e686b7aa..2581c213 100644 --- a/configure.ac +++ b/configure.ac @@ -40,6 +40,12 @@ AC_PROG_INSTALL AC_PROG_YACC AC_PROG_LEX 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' AM_PROG_CC_C_O diff --git a/main.c b/main.c index a57193e1..5999abf1 100644 --- a/main.c +++ b/main.c @@ -71,11 +71,11 @@ struct list_walk_cookie 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; @@ -254,6 +254,24 @@ static void exithook(void) 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 */ @@ -332,6 +350,8 @@ int main(int argc, char * argv []) init_config(); + atexit(cleanup_main); + updates = lcreat(NULL, 0); if (updates == NULL) { fprintf(stderr, "%s: cannot initialize updater list\n", progname); diff --git a/pgm.c b/pgm.c index 72b6b91d..41fa68ed 100644 --- a/pgm.c +++ b/pgm.c @@ -135,6 +135,17 @@ PROGRAMMER * pgm_new(void) 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) { diff --git a/pgm.h b/pgm.h index c510ebce..812a35f3 100644 --- a/pgm.h +++ b/pgm.h @@ -131,6 +131,7 @@ extern "C" { #endif PROGRAMMER * pgm_new(void); +void pgm_free(PROGRAMMER * const p); void programmer_display(PROGRAMMER * pgm, const char * p); PROGRAMMER * locate_programmer(LISTID programmers, const char * configid); diff --git a/update.c b/update.c index ef8de509..5a2d38bf 100644 --- a/update.c +++ b/update.c @@ -200,6 +200,22 @@ UPDATE * new_update(int op, char * memtype, int filefmt, char * filename) 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) { struct avrpart * v; diff --git a/update.h b/update.h index dde48b9a..4768a1a3 100644 --- a/update.h +++ b/update.h @@ -45,6 +45,7 @@ extern UPDATE * parse_op(char * s); extern UPDATE * dup_update(UPDATE * upd); extern UPDATE * new_update(int op, char * memtype, int filefmt, char * filename); +extern void free_update(UPDATE * upd); extern int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, int nowrite); diff --git a/usbasp.c b/usbasp.c index b653b561..df5637b7 100644 --- a/usbasp.c +++ b/usbasp.c @@ -305,6 +305,7 @@ static int usbOpenDevice(libusb_device_handle **device, int vendor, handle = NULL; } } + libusb_free_device_list(dev_list,1); if (handle != NULL){ errorCode = 0; *device = handle; @@ -401,11 +402,7 @@ static int didUsbInit = 0; /* Interface - prog. */ static int usbasp_open(PROGRAMMER * pgm, char * port) { -#ifdef USE_LIBUSB_1_0 - libusb_init(&ctx); -#else - usb_init(); -#endif + /* usb_init will be done in usbOpenDevice */ if (usbOpenDevice(&PDATA(pgm)->usbhandle, pgm->usbvid, pgm->usbvendor, pgm->usbpid, pgm->usbproduct) != 0) { /* try alternatives */ @@ -474,6 +471,11 @@ static void usbasp_close(PROGRAMMER * pgm) usb_close(PDATA(pgm)->usbhandle); #endif } +#ifdef USE_LIBUSB_1_0 + libusb_exit(ctx); +#else + /* nothing for usb 0.1 ? */ +#endif }