Index: doc/avrdude.texi
===================================================================
--- doc/avrdude.texi	(revision 1022)
+++ doc/avrdude.texi	(working copy)
@@ -1523,6 +1523,7 @@
 
 @smallexample
 programmer
+    parent <id>                                 # <id> is a quoted string
     id       = <id1> [, <id2> [, <id3>] ...] ;  # <idN> are quoted strings
     desc     = <description> ;                  # quoted string
     type     = par | stk500 | ... ;             # programmer type (see below for a list)
@@ -1547,6 +1548,10 @@
 @end smallexample
 
 @noindent
+If a parent is specified, all settings of it (except its ids) are used for the new 
+programmer. These values can be changed by new setting them for the new programmer.
+
+@noindent
 To invert a bit in the pin definitions, use @code{= ~ <num>}.
 
 @noindent
Index: config_gram.y
===================================================================
--- config_gram.y	(revision 1022)
+++ config_gram.y	(working copy)
@@ -128,6 +128,7 @@
 %token K_PAGEL
 %token K_PAR
 %token K_PARALLEL
+%token K_PARENT
 %token K_PART
 %token K_PGMLED
 %token K_PROGRAMMER
@@ -295,7 +296,7 @@
                 progname, infile, lineno);
         exit(1);
       }
-      if (current_prog->type[0] == 0) {
+      if (current_prog->initpgm == NULL) {
         fprintf(stderr, "%s: error at %s:%d: programmer type not specified\n",
                 progname, infile, lineno);
         exit(1);
@@ -312,6 +313,21 @@
       strcpy(current_prog->config_file, infile);
       current_prog->lineno = lineno;
     }
+    |
+  K_PROGRAMMER K_PARENT TKN_STRING
+    {
+      struct programmer_t * pgm = locate_programmer(programmers, $3->value.string);
+      if (pgm == NULL) {
+        fprintf(stderr,
+                "%s: error at %s:%d: parent programmer %s not found\n",
+                progname, infile, lineno, $3->value.string);
+        exit(1);
+      }
+      current_prog = pgm_dup(pgm);
+      strcpy(current_prog->config_file, infile);
+      current_prog->lineno = lineno;
+      free_token($3);
+    }
 ;
 
 
@@ -428,37 +444,37 @@
 ;
 
 prog_parm_type_id:
-  K_PAR             { par_initpgm(current_prog); } |
-  K_SERBB           { serbb_initpgm(current_prog); } |
-  K_STK500          { stk500_initpgm(current_prog); } |
-  K_STK500V2        { stk500v2_initpgm(current_prog); } |
-  K_WIRING          { wiring_initpgm(current_prog); } |
-  K_STK500HVSP      { stk500hvsp_initpgm(current_prog); } |
-  K_STK500PP        { stk500pp_initpgm(current_prog); } |
-  K_STK500GENERIC   { stk500generic_initpgm(current_prog); } |
-  K_ARDUINO         { arduino_initpgm(current_prog); } |
-  K_AVRFTDI         { avrftdi_initpgm(current_prog); } |
-  K_BUSPIRATE       { buspirate_initpgm(current_prog); } |
-  K_STK600          { stk600_initpgm(current_prog); } |
-  K_STK600HVSP      { stk600hvsp_initpgm(current_prog); } |
-  K_STK600PP        { stk600pp_initpgm(current_prog); } |
-  K_AVR910          { avr910_initpgm(current_prog); } |
-  K_USBASP          { usbasp_initpgm(current_prog); } |
-  K_USBTINY         { usbtiny_initpgm(current_prog); } |
-  K_BUTTERFLY       { butterfly_initpgm(current_prog); } |
-  K_BUTTERFLY_MK    { butterfly_mk_initpgm(current_prog); } |
-  K_JTAG_MKI        { jtagmkI_initpgm(current_prog); } |
-  K_JTAG_MKII       { jtagmkII_initpgm(current_prog); } |
-  K_JTAG_MKII_AVR32 { jtagmkII_avr32_initpgm(current_prog); } |
-  K_JTAG_MKII_DW    { jtagmkII_dw_initpgm(current_prog); } |
-  K_JTAG_MKII_ISP   { stk500v2_jtagmkII_initpgm(current_prog); } |
-  K_JTAG_MKII_PDI   { jtagmkII_pdi_initpgm(current_prog); } |
-  K_DRAGON_DW       { jtagmkII_dragon_dw_initpgm(current_prog); } |
-  K_DRAGON_HVSP     { stk500v2_dragon_hvsp_initpgm(current_prog); } |
-  K_DRAGON_ISP      { stk500v2_dragon_isp_initpgm(current_prog); } |
-  K_DRAGON_JTAG     { jtagmkII_dragon_initpgm(current_prog); } |
-  K_DRAGON_PDI      { jtagmkII_dragon_pdi_initpgm(current_prog); } |
-  K_DRAGON_PP       { stk500v2_dragon_pp_initpgm(current_prog); }
+  K_PAR             { current_prog->initpgm = par_initpgm; } |
+  K_SERBB           { current_prog->initpgm = serbb_initpgm; } |
+  K_STK500          { current_prog->initpgm = stk500_initpgm; } |
+  K_STK500V2        { current_prog->initpgm = stk500v2_initpgm; } |
+  K_WIRING          { current_prog->initpgm = wiring_initpgm; } |
+  K_STK500HVSP      { current_prog->initpgm = stk500hvsp_initpgm; } |
+  K_STK500PP        { current_prog->initpgm = stk500pp_initpgm; } |
+  K_STK500GENERIC   { current_prog->initpgm = stk500generic_initpgm; } |
+  K_ARDUINO         { current_prog->initpgm = arduino_initpgm; } |
+  K_AVRFTDI         { current_prog->initpgm = avrftdi_initpgm; } |
+  K_BUSPIRATE       { current_prog->initpgm = buspirate_initpgm; } |
+  K_STK600          { current_prog->initpgm = stk600_initpgm; } |
+  K_STK600HVSP      { current_prog->initpgm = stk600hvsp_initpgm; } |
+  K_STK600PP        { current_prog->initpgm = stk600pp_initpgm; } |
+  K_AVR910          { current_prog->initpgm = avr910_initpgm; } |
+  K_USBASP          { current_prog->initpgm = usbasp_initpgm; } |
+  K_USBTINY         { current_prog->initpgm = usbtiny_initpgm; } |
+  K_BUTTERFLY       { current_prog->initpgm = butterfly_initpgm; } |
+  K_BUTTERFLY_MK    { current_prog->initpgm = butterfly_mk_initpgm; } |
+  K_JTAG_MKI        { current_prog->initpgm = jtagmkI_initpgm; } |
+  K_JTAG_MKII       { current_prog->initpgm = jtagmkII_initpgm; } |
+  K_JTAG_MKII_AVR32 { current_prog->initpgm = jtagmkII_avr32_initpgm; } |
+  K_JTAG_MKII_DW    { current_prog->initpgm = jtagmkII_dw_initpgm; } |
+  K_JTAG_MKII_ISP   { current_prog->initpgm = stk500v2_jtagmkII_initpgm; } |
+  K_JTAG_MKII_PDI   { current_prog->initpgm = jtagmkII_pdi_initpgm; } |
+  K_DRAGON_DW       { current_prog->initpgm = jtagmkII_dragon_dw_initpgm; } |
+  K_DRAGON_HVSP     { current_prog->initpgm = stk500v2_dragon_hvsp_initpgm; } |
+  K_DRAGON_ISP      { current_prog->initpgm = stk500v2_dragon_isp_initpgm; } |
+  K_DRAGON_JTAG     { current_prog->initpgm = jtagmkII_dragon_initpgm; } |
+  K_DRAGON_PDI      { current_prog->initpgm = jtagmkII_dragon_pdi_initpgm; } |
+  K_DRAGON_PP       { current_prog->initpgm = stk500v2_dragon_pp_initpgm; }
 ;
 
 prog_parm_usb:
@@ -508,6 +524,8 @@
   TKN_NUMBER { assign_pin(pin_name, $1, 0);  }
   |
   TKN_TILDE TKN_NUMBER { assign_pin(pin_name, $2, 1); }
+  |
+  /* empty */ { current_prog->pinno[pin_name] = 0; }
 ;
 
 pin_list:
@@ -527,6 +545,10 @@
       }
     }
   }
+  |
+  /* empty */ {
+    current_prog->pinno[pin_name] = 0;
+  }
 ;
 
 prog_parm_pins:
Index: avrdude.conf.in
===================================================================
--- avrdude.conf.in	(revision 1022)
+++ avrdude.conf.in	(working copy)
@@ -13,6 +13,7 @@
 # Possible entry formats are:
 #
 #   programmer
+#       parent <id>                                 # optional parent
 #       id       = <id1> [, <id2> [, <id3>] ...] ;  # <idN> are quoted strings
 #       desc     = <description> ;                  # quoted string
 #       type     = par | stk500 | stk500v2 | stk500pp | stk500hvsp | stk500generic |
@@ -447,10 +448,8 @@
   type  =  stk500v2;
 ;
 
-programmer
+programmer parent "avrispmkII"
   id    = "avrisp2";
-  desc  = "Atmel AVR ISP mkII";
-  type  =  stk500v2;
 ;
 
 programmer
@@ -560,10 +559,8 @@
   type  = butterfly_mk;
 ;
 
-programmer
+programmer parent "mkbutterfly"
   id    = "butterfly_mk";
-  desc  = "Mikrokopter.de Butterfly";
-  type  = butterfly_mk;
 ;
 
 programmer
@@ -574,19 +571,14 @@
 ;
 
 # easier to type
-programmer
+programmer parent "jtagmkI"
   id    = "jtag1";
-  desc  = "Atmel JTAG ICE (mkI)";
-  baudrate = 115200;    # default is 115200
-  type  = jtagmki;
 ;
 
 # easier to type
-programmer
+programmer parent "jtag1"
   id    = "jtag1slow";
-  desc  = "Atmel JTAG ICE (mkI)";
   baudrate = 19200;
-  type  = jtagmki;
 ;
 
 programmer
@@ -597,27 +589,19 @@
 ;
 
 # easier to type
-programmer
+programmer parent "jtagmkII"
   id    = "jtag2slow";
-  desc  = "Atmel JTAG ICE mkII";
-  baudrate = 19200;    # default is 19200
-  type  = jtagmkii;
 ;
 
 # JTAG ICE mkII @ 115200 Bd
-programmer
+programmer parent "jtag2slow"
   id    = "jtag2fast";
-  desc  = "Atmel JTAG ICE mkII";
   baudrate = 115200;
-  type  = jtagmkii;
 ;
 
 # make the fast one the default, people will love that
-programmer
+programmer parent "jtag2fast"
   id    = "jtag2";
-  desc  = "Atmel JTAG ICE mkII";
-  baudrate = 115200;
-  type  = jtagmkii;
 ;
 
 # JTAG ICE mkII in ISP mode
@@ -744,15 +728,9 @@
 # except that there is a LED indicating that the
 # programming is currently in progress.
 
-programmer
+programmer parent "stk200"
   id    = "pony-stk200";
   desc  = "Pony Prog STK200";
-  type  = par;
-  buff  = 4, 5;
-  sck   = 6;
-  mosi  = 7;
-  reset = 9;
-  miso  = 10;
   pgmled = 8; 
 ;
 
@@ -766,14 +744,9 @@
   miso  = 11;
 ;
 
-programmer
+programmer parent "dt006"
   id    = "bascom";
   desc  = "Bascom SAMPLE programming cable";
-  type  = par;
-  reset = 4;
-  sck   = 5;
-  mosi  = 2;
-  miso  = 11;
 ;
 
 programmer
@@ -898,16 +871,11 @@
 
 # It is almost same as pony-stk200, except vcc on pin 5 to auto
 # disconnect port (download on http://electropol.free.fr)
-programmer
+programmer parent "pony-stk200"
   id    = "frank-stk200";
   desc  = "Frank STK200";
-  type  = par;
+  buff  = ; # delete buff pin assignment
   vcc   = 5;
-  sck   = 6;
-  mosi  = 7;
-  reset = 9;
-  miso  = 10;
-  pgmled = 8;
 ;
 
 # The AT98ISP Cable is a simple parallel dongle for AT89 family.
@@ -959,14 +927,9 @@
 # Same as above, different name
 # reset=!txd sck=rts mosi=dtr miso=cts
 
-programmer
+programmer parent "ponyser"
   id    = "siprog";
   desc  = "Lancos SI-Prog <http://www.lancos.com/siprogsch.html>";
-  type  = serbb;
-  reset = ~3;
-  sck   = 7;
-  mosi  = 4;
-  miso  = 8;
 ;
 
 # unknown (dasa in uisp)
Index: pgm.c
===================================================================
--- pgm.c	(revision 1022)
+++ pgm.c	(working copy)
@@ -82,6 +82,7 @@
   pgm->config_file[0] = 0;
   pgm->lineno = 0;
   pgm->baudrate = 0;
+  pgm->initpgm = NULL;
 
   for (i=0; i<N_PINS; i++)
     pgm->pinno[i] = 0;
@@ -136,6 +137,25 @@
 }
 
 
+PROGRAMMER * pgm_dup(const PROGRAMMER const * src)
+{
+  PROGRAMMER * pgm;
+
+  pgm = (PROGRAMMER *)malloc(sizeof(*pgm));
+  if (pgm == NULL) {
+    fprintf(stderr, "%s: out of memory allocating programmer structure\n",
+            progname);
+    exit(1);
+  }
+
+  memcpy(pgm, src, sizeof(*pgm));
+
+  pgm->id = lcreat(NULL, 0);
+
+  return pgm;
+}
+
+
 static void pgm_default(void)
 {
   fprintf(stderr, "%s: programmer operation not supported\n", progname);
Index: main.c
===================================================================
--- main.c	(revision 1022)
+++ main.c	(working copy)
@@ -673,6 +673,10 @@
     exit(1);
   }
 
+  if (pgm->initpgm) {
+    pgm->initpgm(pgm);
+  }
+
   if (pgm->setup) {
     pgm->setup(pgm);
   }
Index: lexer.l
===================================================================
--- lexer.l	(revision 1022)
+++ lexer.l	(working copy)
@@ -177,6 +177,7 @@
 pagel            { yylval=NULL; return K_PAGEL; }
 par              { yylval=NULL; return K_PAR; }
 parallel         { yylval=NULL; return K_PARALLEL; }
+parent           { yylval=NULL; return K_PARENT; }
 part             { yylval=NULL; return K_PART; }
 pgmled           { yylval=NULL; return K_PGMLED; }
 programmer       { yylval=NULL; return K_PROGRAMMER; }
Index: pgm.h
===================================================================
--- pgm.h	(revision 1022)
+++ pgm.h	(working copy)
@@ -61,6 +61,7 @@
   char desc[PGM_DESCLEN];
   char type[PGM_TYPELEN];
   char port[PGM_PORTLEN];
+  void (*initpgm)(struct programmer_t * pgm);
   unsigned int pinno[N_PINS];
   exit_vcc_t exit_vcc;
   exit_reset_t exit_reset;
@@ -131,6 +132,7 @@
 #endif
 
 PROGRAMMER * pgm_new(void);
+PROGRAMMER * pgm_dup(const PROGRAMMER const * src);
 
 void programmer_display(PROGRAMMER * pgm, const char * p);
 PROGRAMMER * locate_programmer(LISTID programmers, const char * configid);
