diff --git a/avrdude/ChangeLog b/avrdude/ChangeLog
index 5851ad22..7e748b1a 100644
--- a/avrdude/ChangeLog
+++ b/avrdude/ChangeLog
@@ -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>
 
 	* usbasp.c: USB vid/pid/vendor/product from config file are used, for
diff --git a/avrdude/Makefile.am b/avrdude/Makefile.am
index 49a3182b..343a56dc 100644
--- a/avrdude/Makefile.am
+++ b/avrdude/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/avrdude/avrpart.c b/avrdude/avrpart.c
index 0dba3f64..280721be 100644
--- a/avrdude/avrpart.c
+++ b/avrdude/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;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)
 {
@@ -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;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)
 {
diff --git a/avrdude/avrpart.h b/avrdude/avrpart.h
index 70bdb085..90a6f267 100644
--- a/avrdude/avrpart.h
+++ b/avrdude/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/avrdude/buspirate.c b/avrdude/buspirate.c
index d2034aab..090b54c8 100644
--- a/avrdude/buspirate.c
+++ b/avrdude/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/avrdude/config.c b/avrdude/config.c
index 6f0b571d..8a13befb 100644
--- a/avrdude/config.c
+++ b/avrdude/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/avrdude/config.h b/avrdude/config.h
index 02355795..835e9c3b 100644
--- a/avrdude/config.h
+++ b/avrdude/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/avrdude/config_gram.y b/avrdude/config_gram.y
index 64eb2750..45f0ce30 100644
--- a/avrdude/config_gram.y
+++ b/avrdude/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/avrdude/configure.ac b/avrdude/configure.ac
index e686b7aa..2581c213 100644
--- a/avrdude/configure.ac
+++ b/avrdude/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/avrdude/main.c b/avrdude/main.c
index a57193e1..5999abf1 100644
--- a/avrdude/main.c
+++ b/avrdude/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/avrdude/pgm.c b/avrdude/pgm.c
index 72b6b91d..41fa68ed 100644
--- a/avrdude/pgm.c
+++ b/avrdude/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/avrdude/pgm.h b/avrdude/pgm.h
index c510ebce..812a35f3 100644
--- a/avrdude/pgm.h
+++ b/avrdude/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/avrdude/update.c b/avrdude/update.c
index ef8de509..5a2d38bf 100644
--- a/avrdude/update.c
+++ b/avrdude/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/avrdude/update.h b/avrdude/update.h
index dde48b9a..4768a1a3 100644
--- a/avrdude/update.h
+++ b/avrdude/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/avrdude/usbasp.c b/avrdude/usbasp.c
index b653b561..df5637b7 100644
--- a/avrdude/usbasp.c
+++ b/avrdude/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
 }