Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.487
diff -u -p -r1.487 form.inc
--- includes/form.inc	30 Aug 2010 17:07:49 -0000	1.487
+++ includes/form.inc	5 Sep 2010 05:21:38 -0000
@@ -1480,7 +1480,7 @@ function form_error(&$element, $message 
  *   was clicked when the form was submitted, as well as the sanitized
  *   $_POST data.
  */
-function form_builder($form_id, $element, &$form_state) {
+function form_builder($form_id, &$element, &$form_state) {
   // Initialize as unprocessed.
   $element['#processed'] = FALSE;
 
@@ -1508,7 +1508,7 @@ function form_builder($form_id, $element
     }
 
     // Store a complete copy of the form in form_state prior to building the form.
-    $form_state['complete form'] = $element;
+    $form_state['complete form'] = &$element;
     // Set a flag if we have a correct form submission. This is always TRUE for
     // programmed forms coming from drupal_form_submit(), or if the form_id coming
     // from the POST data is set and matches the current form_id.
@@ -1654,9 +1654,6 @@ function form_builder($form_id, $element
       // @todo Legacy support. Remove in Drupal 8.
       $form_state['clicked_button'] = $form_state['triggering_element'];
     }
-
-    // Update the copy of the complete form for usage in validation handlers.
-    $form_state['complete form'] = $element;
   }
   return $element;
 }
@@ -2867,6 +2864,64 @@ function form_process_tableselect($eleme
   return $element;
 }
 
+function form_process_machine_name($element, &$form_state) {
+  if (empty($element['#target'])) {
+    return $element;
+  }
+  list($source, $value_exists) = drupal_array_get_nested_value($form_state['complete form'], $element['#target']);
+
+  if (!isset($source['#suffix'])) {
+    $source['#suffix'] = '';
+  }
+  $suffix_id = $source['#id'] . '-machine-name-suffix';
+  $source['#suffix'] .= '  <small id="' . $suffix_id . '">&nbsp;</small>';
+
+  $js_settings = array(
+    'type' => 'setting',
+    'data' => array(
+      'machineReadableValue' => array(
+        '#' . $source['#id'] => array(
+          'text' => $element['#title'],
+          'target' => '#' . $element['#id'],
+          'searchPattern' => $element['#machine_name_pattern'],
+          'replaceToken' => $element['#machine_name_replace'],
+          'suffix' => '#' . $suffix_id,
+        ),
+      ),
+    ),
+  );
+
+  $element['#attached']['js'][] = drupal_get_path('module', 'system') . '/system.js';
+  $element['#attached']['js'][] = $js_settings;
+  return $element;
+}
+
+function form_validate_machine_name(&$element, &$form_state) {
+  // Restrict machine names to appropriate characters.
+  if (!preg_match('@^[a-z0-9_]+$@', $element['#value'])) {
+    if (!isset($element['#machine_name_error'])) {
+      form_error($element, t('The machine-readable name must contain only lowercase letters, numbers, and underscores.'));
+    }
+    else {
+      form_error($element, $element['#machine_name_error']);
+    }
+  }
+  // Validate length.
+  if (!empty($element['#maxlength']) && drupal_strlen($element['#value']) > $element['#maxlength']) {
+    form_set_error('machine_name', t('The machine-readable name must not exceed @count characters.', array(
+      '@count' => $element['#maxlength'],
+    )));
+  }
+  // Prevent duplicate machine names.
+  // @todo 
+  #list($value, $value_exists) = drupal_array_get_nested_value($form_state['values'], $element['#machine_name_);
+  foreach (filter_formats() as $format) {
+    if ($element['#value'] == $format->machine_name && (!isset($form_state['values']['format']) || $format->format != $form_state['values']['format'])) {
+      form_error($element, t('This machine-readable name is already in use and must be unique.'));
+    }
+  }
+}
+
 /**
  * Adds fieldsets to the specified group or adds group members to this
  * fieldset.
Index: modules/system/system.js
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.js,v
retrieving revision 1.40
diff -u -p -r1.40 system.js
--- modules/system/system.js	30 Jan 2010 00:29:10 -0000	1.40
+++ modules/system/system.js	5 Sep 2010 05:18:41 -0000
@@ -164,48 +164,48 @@ Drupal.behaviors.pageCache = {
  * @see menu_edit_menu()
  */
 Drupal.behaviors.machineReadableValue = {
-  attach: function () {
+  attach: function (context) {
     var self = this;
 
     for (var value in Drupal.settings.machineReadableValue) {
       var settings = Drupal.settings.machineReadableValue[value];
 
       // Build selector for the source name entered by a user.
-      var source = '#edit-' + value;
-      var suffix = source + '-suffix';
+      var $source = $(value, context);
+      var suffix = settings.suffix;
       // Build selector for the machine readable name.
-      var target = '#edit-' + settings.target;
+      var $target = $(settings.target, context);
       // Build selector for the wrapper element around the target field.
-      var wrapper = '.form-item-' + settings.target;
+      var $wrapper = $target.parents('.form-item:first');
 
       // Do not process the element if we got an error or the given name and the
       // machine readable name are identical or the machine readable name is
       // empty.
-      if (!$(target).hasClass('error') && ($(target).val() == '' || $(target).val() == self.transliterate($(source).val(), settings))) {
+      if (!$target.hasClass('error') && ($target.val() == '' || $target.val() == self.transliterate($source.val(), settings))) {
         // Hide wrapper element.
-        $(wrapper).hide();
+        $wrapper.hide();
         // Bind keyup event to source element.
-        $(source).keyup(function () {
+        $source.keyup(function () {
           var machine = self.transliterate($(this).val(), settings);
           if (machine != '_' && machine != '') {
             // Set machine readable name to the user entered value.
-            $(target).val(machine);
+            $target.val(machine);
             // Append the machine readable name and a link to edit it to the source field.
             $(suffix).empty().append(' ' + settings.text + ': ' + machine + ' [').append($('<a href="#">' + Drupal.t('Edit') + '</a>').click(function () {
-              $(wrapper).show();
-              $(target).focus();
+              $wrapper.show();
+              $target.focus();
               $(suffix).hide();
-              $(source).unbind('keyup');
+              $source.unbind('keyup');
               return false;
             })).append(']');
           }
           else {
-            $(target).val(machine);
+            $target.val(machine);
             $(suffix).text('');
           }
         });
         // Call keyup event on source element.
-        $(source).keyup();
+        $source.keyup();
       }
     }
   },
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.959
diff -u -p -r1.959 system.module
--- modules/system/system.module	5 Sep 2010 02:21:38 -0000	1.959
+++ modules/system/system.module	5 Sep 2010 05:20:58 -0000
@@ -346,6 +346,21 @@ function system_element_info() {
     '#theme' => 'textfield',
     '#theme_wrappers' => array('form_element'),
   );
+  $types['machine_name'] = array(
+    '#input' => TRUE,
+    '#title' => t('Machine-readable name'),
+    '#description' => t('A unique machine-readable name. Can only contain lowercase letters, numbers, and underscores.'),
+    '#target' => array('name'),
+    '#machine_name_pattern' => '[^a-z0-9]+',
+    '#machine_name_replace' => '_',
+    '#required' => TRUE,
+    '#maxlength' => 64,
+    '#size' => 60,
+    '#autocomplete_path' => FALSE,
+    '#process' => array('form_process_machine_name', 'ajax_process_form'),
+    '#theme' => 'textfield',
+    '#theme_wrappers' => array('form_element'),
+  );
   $types['password'] = array(
     '#input' => TRUE,
     '#size' => 60,
Index: modules/taxonomy/taxonomy.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.admin.inc,v
retrieving revision 1.107
diff -u -p -r1.107 taxonomy.admin.inc
--- modules/taxonomy/taxonomy.admin.inc	31 Jul 2010 13:01:50 -0000	1.107
+++ modules/taxonomy/taxonomy.admin.inc	5 Sep 2010 05:22:23 -0000
@@ -137,31 +137,11 @@ function taxonomy_form_vocabulary($form,
     '#default_value' => $vocabulary->name,
     '#maxlength' => 255,
     '#required' => TRUE,
-    '#field_suffix' => ' <small id="edit-name-suffix">&nbsp;</small>',
-  );
-  $js_settings = array(
-    'type' => 'setting',
-    'data' => array(
-      'machineReadableValue' => array(
-        'name' => array(
-          'text' => t('Machine name'),
-          'target' => 'machine-name',
-          'searchPattern' => '[^a-z0-9]+',
-          'replaceToken' => '_',
-        ),
-      ),
-    ),
   );
   $form['machine_name'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Machine-readable name'),
+    '#type' => 'machine_name',
     '#default_value' => $vocabulary->machine_name,
     '#maxlength' => 255,
-    '#description' => t('The unique machine-readable name for this vocabulary, used for theme templates. Can only contain lowercase letters, numbers, and underscores.'),
-    '#required' => TRUE,
-    '#attached' => array(
-      'js' => array(drupal_get_path('module', 'system') . '/system.js', $js_settings),
-    ),
   );
   $form['description'] = array(
     '#type' => 'textfield',
