Index: scripts/coder_format/coder_format.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/coder/scripts/coder_format/coder_format.inc,v
retrieving revision 1.2.4.5
diff -u -p -r1.2.4.5 coder_format.inc
--- scripts/coder_format/coder_format.inc	16 Jan 2008 22:26:33 -0000	1.2.4.5
+++ scripts/coder_format/coder_format.inc	20 Jan 2008 20:53:31 -0000
@@ -1,9 +1,10 @@
 <?php
 // $Id: coder_format.inc,v 1.2.4.5 2008/01/16 22:26:33 sun Exp $
 
+
 /**
  * Recursively process .module and .inc files in directory with coder_format_file().
- * 
+ *
  * @param $root
  *   Path to root directory for Drupal installation.
  * @param $undo
@@ -14,18 +15,18 @@
 function coder_format_recursive($root, $undo = false, $file_inc = null) {
   // Convert Windows paths.
   $root = str_replace("\\", '/', $root);
-  
+
   // Check if directory exists.
   if (!file_exists($root)) {
     echo 'ERROR: '. $root .' does not exist!';
     return;
   }
-  
+
   // Trim root directory.
   if (substr($root, -1) == '/') {
     $root = substr($root, 0, -1);
   }
-  
+
   // Include Drupal's file.inc.
   if (!isset($file_inc)) {
     if (!file_exists($root .'/includes/file.inc')) {
@@ -40,12 +41,12 @@ function coder_format_recursive($root, $
     }
   }
   require_once (!isset($file_inc) ? $root .'/includes/file.inc' : $file_inc);
-  
+
   if (!$undo) {
     // Fetch files to process.
-    $mask = '.module$|.inc$|.install|.profile$';
+    $mask   = '\.php$|\.module$|\.inc$|\.install|\.profile$';
     $nomask = array('.', '..', 'CVS', '.svn');
-    $files = file_scan_directory($root, $mask, $nomask, 0, true);
+    $files  = file_scan_directory($root, $mask, $nomask, 0, true);
     foreach ($files as $file) {
       // file_copy() assigns $file->filename by reference.
       $sourcefile = $file->filename;
@@ -56,9 +57,9 @@ function coder_format_recursive($root, $
   }
   else {
     // Fetch files to process.
-    $mask = '.coder.orig$';
+    $mask   = '.coder.orig$';
     $nomask = array('.', '..', 'CVS', '.svn');
-    $files = file_scan_directory($root, $mask, $nomask, 0, true);
+    $files  = file_scan_directory($root, $mask, $nomask, 0, true);
     foreach ($files as $file) {
       $file->origname = str_replace('.coder.orig', '', $file->filename);
       echo $file->origname ."\n";
@@ -69,11 +70,12 @@ function coder_format_recursive($root, $
 
 /**
  * Reads, processes and writes the source code from and to a file.
- * 
+ *
  * @param $sourcefile
  *   Path to source file to read code from.
  * @param $targetfile
  *   Target path to write formatted source code to.
+ *
  * @return
  *   TRUE if successful.
  */
@@ -81,25 +83,15 @@ function coder_format_file($sourcefile =
   if (!isset($sourcefile) || !isset($targetfile)) {
     return;
   }
-  
+
   // Read source code from source file.
   $fd = fopen($sourcefile, 'r');
   $code = fread($fd, filesize($sourcefile));
   fclose($fd);
-  
+
   if ($code !== false) {
-    // Preprocess source code.
-    $code = coder_exec_processors($code, 'coder_preprocessor');
-    
-    // Process source code.
-    $code = coder_format_string($code);
-    
-    // Postprocess source code.
-    $code = coder_exec_processors($code, 'coder_postprocessor');
-    
-    // Fix beginning and end of code.
-    $code = coder_trim_php($code);
-    
+    $code = coder_format_string_all($code);
+
     if ($code !== false) {
       // Write formatted source code to target file.
       $fd = fopen($targetfile, 'w');
@@ -108,11 +100,34 @@ function coder_format_file($sourcefile =
       return $status;
     }
   }
-  
+
   return false;
 }
 
 /**
+ * Formats source code according to Drupal conventions, also using
+ * post and pre-processors.
+ *
+ * @param
+ *   $code Code to process.
+ */
+function coder_format_string_all($code) {
+  // Preprocess source code.
+  $code = coder_exec_processors($code, 'coder_preprocessor');
+
+  // Process source code.
+  $code = coder_format_string($code);
+
+  // Postprocess source code.
+  $code = coder_exec_processors($code, 'coder_postprocessor');
+
+  // Fix beginning and end of code.
+  $code = coder_trim_php($code);
+
+  return $code;
+}
+
+/**
  * Format the source code according to Drupal coding style guidelines.
  *
  * This function uses PHP's tokenizer functions.
@@ -166,6 +181,20 @@ function coder_format_file($sourcefile =
  *   $inline_if bool
  *      Controls formatting of ? and : for inline ifs until a ; (semicolon) is
  *      processed.
+ *   $in_function_declaration
+ *      Prevents whitespace after & for function declarations, e.g.
+ *      function &foo(). Is true after function token but before first
+ *      parenthesis.
+ *   $in_array
+ *      Array of parenthesis level to whether or not the structure
+ *      is for an array.
+ *   $in_multiline
+ *      Array of parenthesis level to whether or not the structure
+ *      is multiline.
+ *   $after_semicolon
+ *      Whether or not the current line being processed has a semicolon.
+ *   $after_case
+ *      Whether or not the current line being processed has a case/default statement.
  *
  * @param $code
  *      The source code to format.
@@ -175,7 +204,7 @@ function coder_format_file($sourcefile =
  */
 function coder_format_string($code = '') {
   global $_coder_indent;
-  
+
   // Indent controls:
   $_coder_indent  = 0;
   $in_case        = false;
@@ -185,17 +214,24 @@ function coder_format_string($code = '')
   $in_heredoc     = false;
   $first_php_tag  = true;
   $in_do_while    = false;
-  
+
   // Whitespace controls:
-  $in_object   = false;
-  $in_at       = false;
-  $in_php      = false;
-  $in_quote    = false;
-  $inline_if   = false;
-  
-  $result      = '';
-  $lasttoken   = array(0);
-  $tokens      = token_get_all($code);
+  $in_object       = FALSE;
+  $in_at           = FALSE;
+  $in_php          = FALSE;
+  $in_quote        = FALSE;
+  $inline_if       = FALSE;
+  $in_array        = array();
+  $in_multiline    = array();
+  $after_semicolon = FALSE;
+  $after_case      = FALSE;
+
+  // Whether or not a function token was encountered:
+  $in_function_declaration = FALSE;
+
+  $result = '';
+  $lasttoken = array(0);
+  $tokens = token_get_all($code);
 
   // Mask T_ML_COMMENT (PHP4) as T_COMMENT (PHP5).
   // Mask T_DOC_COMMENT (PHP5) as T_ML_COMMENT (PHP4).
@@ -205,7 +241,7 @@ function coder_format_string($code = '')
   else if (!defined('T_DOC_COMMENT')) {
     define('T_DOC_COMMENT', T_ML_COMMENT);
   }
-  
+
   foreach ($tokens as $token) {
     if (is_string($token)) {
       // Simple 1-character token.
@@ -215,19 +251,20 @@ function coder_format_string($code = '')
           // Write curly braces at the end of lines followed by a line break if
           // not in quotes (""), object ($foo->{$bar}) or in variables (${foo}).
           // (T_DOLLAR_OPEN_CURLY_BRACES exists but is never assigned.)
-          if (!$in_quote && !$in_object && substr(rtrim($result), -1) != '$') {
+          if (!$in_variable && !$in_quote && !$in_object && substr(rtrim($result), -1) != '$') {
             if ($in_case) {
               ++$braces_in_case;
             }
             ++$_coder_indent;
-            $result = rtrim($result) .' '. $text . coder_br();
+            $result = rtrim($result) .' '. $text;
+            coder_br($result);
           }
           else {
             $in_brace = true;
             $result .= $text;
           }
           break;
-        
+
         case '}':
           if (!$in_quote && !$in_brace && !$in_heredoc) {
             if ($in_case) {
@@ -243,20 +280,22 @@ function coder_format_string($code = '')
             $result = rtrim($result);
             if (substr($result, -1) != '{') {
               // Avoid line break in empty curly braces.
-              $result .= coder_br();
+              coder_br($result);
             }
-            $result .= $text . coder_br();
+            $result .= $text;
+            coder_br($result);
           }
           else {
             $in_brace = false;
             $result .= $text;
           }
           break;
-        
+
         case ';':
           $result = rtrim($result) . $text;
           if (!$parenthesis && !$in_heredoc) {
-            $result .= coder_br();
+            coder_br($result);
+            $after_semicolon = TRUE;
           }
           else {
             $result .= ' ';
@@ -265,12 +304,12 @@ function coder_format_string($code = '')
             $inline_if = false;
           }
           break;
-        
+
         case '?':
           $inline_if = true;
           $result .= ' '. $text .' ';
           break;
-        
+
         case ':':
           if ($inline_if) {
             $result .= ' '. $text .' ';
@@ -279,40 +318,71 @@ function coder_format_string($code = '')
             if ($in_case) {
               ++$_coder_indent;
             }
-            $result = rtrim($result) . $text . coder_br();
+            $result = rtrim($result) . $text;
+            coder_br($result);
           }
           break;
-        
+
         case '(':
           $result .= $text;
           ++$parenthesis;
+          // Not multiline until proven so by whitespace.
+          $in_multiline[$parenthesis] = FALSE;
+          // If the $in_array flag for this parenthesis level was not
+          // set previously, set it to FALSE.
+          if (!isset($in_array[$parenthesis])) {
+            $in_array[$parenthesis] = FALSE;
+          }
+          // Terminate function declaration, as a parenthesis indicates
+          // the beginning of the arguments. This will catch all other
+          // instances of parentheses, but in this case it's not a problem.
+          $in_function_declaration = FALSE;
           break;
-        
+
         case ')':
-          if (!$in_quote && !$in_heredoc && substr(rtrim($result), -1) == ',') {
-            // Fix indent of right parenthesis in multiline arrays by
+          if ($in_array[$parenthesis] && $in_multiline[$parenthesis]) {
+            // Check if a comma insertion is necessary:
+            for ($c = strlen($result) - 1; $c >= 0; $c--) {
+              if ($result[$c] === "\n" || $result[$c] === " ") {
+                continue;
+              }
+              if ($result[$c] === ",") {
+                break;
+              }
+              // We need to add a comma at $c:
+              $result = substr($result, 0, $c + 1) .','. substr($result, $c + 1);
+              break;
+            }
+          }
+          if (!$in_quote && !$in_heredoc && (substr(rtrim($result), -1) == ',' || $in_multiline[$parenthesis])) {
+            // Fix indent of right parenthesis in multiline structures by
             // increasing indent for each parenthesis and decreasing one level.
-            $_coder_indent = $_coder_indent + $parenthesis - 1;
-            $result = rtrim($result) . coder_br() . $text;
-            $_coder_indent = $_coder_indent - $parenthesis + 1;
+            $_coder_indent = $_coder_indent + ($parenthesis - 1);
+            $result = rtrim($result);
+            coder_br($result);
+            $result .= $text;
+            // Undo temporary change.
+            $_coder_indent = $_coder_indent - ($parenthesis - 1);
           }
           else {
             $result .= $text;
           }
           if ($parenthesis) {
+            // Current parenthesis level is not an array anymore.
+            $in_array[$parenthesis] = FALSE;
             --$parenthesis;
           }
           break;
-        
+
         case '@':
           $in_at = true;
           $result .= $text;
           break;
-        
+
         case ',':
           $result .= $text .' ';
           break;
-        
+
         case '.':
           if (substr(rtrim($result), -1) == "'" || substr(rtrim($result), -1) == '"') {
             // Write string concatenation character directly after strings.
@@ -322,7 +392,7 @@ function coder_format_string($code = '')
             $result = rtrim($result) .' '. $text .' ';
           }
           break;
-        
+
         case '=':
         case '<':
         case '>':
@@ -334,27 +404,39 @@ function coder_format_string($code = '')
         case '%':
           $result = rtrim($result) .' '. $text .' ';
           break;
-        
+
         case '&':
           if (substr(rtrim($result), -1) == '=' || substr(rtrim($result), -1) == '(' || substr(rtrim($result), -1) == ',') {
             $result .= $text;
           }
           else {
-            $result = rtrim($result) .' '. $text .' ';
+            $result = rtrim($result) .' '. $text;
+            // Ampersands used to declare reference return value for
+            // functions should not have trailing space.
+            if (!$in_function_declaration) {
+              $result .= ' ';
+            }
           }
           break;
 
         case '-':
           $result = rtrim($result);
           // Do not add a space before negative numbers or variables.
-          if (substr($result, -1) == '>' || substr($result, -1) == '=' || substr($result, -1) == ',' || substr($result, -1) == ':') {
+          $c = substr($result, -1);
+          // Do not add a space between closing parenthesis and negative arithmetic operators.
+          if ($c == '(') {
+            $result .= ltrim($text);
+          }
+          // Add a space in front of the following chars, but not after them.
+          elseif ($c == '>' || $c == '=' || $c == ',' || $c == ':' || $c == '?') {
             $result .= ' '. $text;
           }
+          // Default arithmetic operator behavior.
           else {
             $result .= ' '. $text .' ';
           }
           break;
-        
+
         case '"':
           // Toggle quote if the char is not escaped.
           if (rtrim($result) != "\\") {
@@ -366,7 +448,7 @@ function coder_format_string($code = '')
           }
           $result .= $text;
           break;
-        
+
         default:
           $result .= $text;
           break;
@@ -375,40 +457,43 @@ function coder_format_string($code = '')
     else {
       // If we get here, then we have found not a single char, but a token.
       // See <http://www.php.net/manual/en/tokens.php> for a reference.
-      
+
       // Fetch token array.
       list($id, $text) = $token;
-      
+
       // Debugging:
       /*
       if ($lasttoken[0] == T_WHITESPACE) {
         $result .= token_name($id);
       }
       */
-      
+
       switch ($id) {
         case T_ARRAY:
           // Write array in lowercase.
           $result .= strtolower(trim($text));
+          // Mark the next parenthesis level (we haven't consumed that token
+          // yet) as an array.
+          $in_array[$parenthesis + 1] = TRUE;
           break;
-        
+
         case T_OPEN_TAG:
         case T_OPEN_TAG_WITH_ECHO:
           $in_php = true;
           // Add a line break between two PHP tags.
           if (substr(rtrim($result), -2) == '?>') {
-            $result .= coder_br();
+            coder_br($result);
           }
           $result .= trim($text);
           if ($first_php_tag) {
-            $result .= coder_br();
-            $first_php_tag = false;
+            coder_br($result);
+            $first_php_tag = FALSE;
           }
           else {
             $result .= ' ';
           }
           break;
-        
+
         case T_CLOSE_TAG:
           $in_php = false;
           // Remove preceding line break for inline PHP output in HTML.
@@ -417,57 +502,80 @@ function coder_format_string($code = '')
           }
           $result .= trim($text);
           break;
-        
+
         case T_OBJECT_OPERATOR:
           $in_object = true;
           $result .= trim($text);
           break;
-        
+
         case T_CONSTANT_ENCAPSED_STRING:
-          if (substr($result, -2) == '. ') {
-            // Write string concatenation character directly before strings.
+          // Handle special string concatenation case: 'bar' . 'baz'
+          $c = substr($result, -3);
+          if ($c == '". ' || $c == '\'. ') {
+            $result = rtrim($result, ' .');
+            $result .= ' . ';
+          }
+          // Handle special string concatenation case: 'bar'. $foo
+          elseif (substr($result, -2) == '. ') {
             $result = rtrim($result);
           }
           // Move on to T_STRING / T_VARIABLE.
         case T_STRING:
         case T_VARIABLE:
+          // No space after object operator ($foo->bar) and error suppression (@function()).
           if ($in_object || $in_at) {
-            // No space after object operator ($foo->bar) and error suppression (@function()).
-            $result = rtrim($result) . trim($text);
+            $result    = rtrim($result) . trim($text);
             $in_object = false;
-            $in_at = false;
+            $in_at     = false;
           }
           else {
+            // Insert a space after right parenthesis, but not after type casts.
             if (!in_array($lasttoken[0], array(T_ARRAY_CAST, T_BOOL_CAST, T_DOUBLE_CAST, T_INT_CAST, T_OBJECT_CAST, T_STRING_CAST, T_UNSET_CAST))) {
-              // Insert a space after right parenthesis, but not after type casts.
               coder_add_space($result);
             }
             $result .= trim($text);
           }
+          $in_variable = true;
           break;
-        
+
         case T_ENCAPSED_AND_WHITESPACE:
           $result .= $text;
           break;
-        
+
         case T_WHITESPACE:
           // Avoid duplicate line feeds outside arrays.
           $c = $parenthesis ? 0 : 1;
-          
-          for ($c, $cc = substr_count($text, chr(10)); $c < $cc; ++$c) {
+
+          for ($c, $cc = substr_count($text, "\n"); $c < $cc; ++$c) {
+            // Newlines were added; not after semicolon anymore
             if ($parenthesis) {
               // Add extra indent for each parenthesis in multiline definitions (f.e. arrays).
               $_coder_indent = $_coder_indent + $parenthesis;
-              $result = rtrim($result) . coder_br();
+              $result = rtrim($result);
+              coder_br($result);
               $_coder_indent = $_coder_indent - $parenthesis;
             }
             else {
               // Discard any whitespace, just insert a line break.
-              $result .= coder_br();
+              coder_br($result);
             }
           }
+
+          // If there were newlines present inside a parenthesis,
+          // turn on multiline mode.
+          if ($cc && $parenthesis) {
+            $in_multiline[$parenthesis] = TRUE;
+          }
+
+          // If there were newlines present, move inline comments above.
+          if ($cc) {
+            $after_semicolon = FALSE;
+            $after_case = FALSE;
+          }
+          
+          $in_variable = FALSE;
           break;
-        
+
         case T_IF:
         case T_FOR:
         case T_FOREACH:
@@ -481,18 +589,19 @@ function coder_format_string($code = '')
         case T_REQUIRE_ONCE:
         case T_INCLUDE:
         case T_INCLUDE_ONCE:
+        case T_VAR:
           coder_add_space($result);
           // Append a space.
           $result .= trim($text) .' ';
           break;
-        
+
         case T_DO:
           $result .= trim($text);
           $in_do_while = true;
           break;
-        
+
         case T_WHILE:
-          if ($in_do_while) {
+          if ($in_do_while && substr(rtrim($result), -1) === '}') {
             // Write while after right parenthesis for do {...} while().
             $result = rtrim($result) .' ';
             $in_do_while = false;
@@ -500,40 +609,46 @@ function coder_format_string($code = '')
           // Append a space.
           $result .= trim($text) .' ';
           break;
-        
+
         case T_ELSE:
         case T_ELSEIF:
           // Write else and else if to a new line.
-          $result = rtrim($result) . coder_br() . trim($text) .' ';
+          $result = rtrim($result);
+          coder_br($result);
+          $result .= trim($text) .' ';
           break;
-        
+
         case T_CASE:
         case T_DEFAULT:
           $braces_in_case = 0;
-          $result = rtrim($result);
+          $result         = rtrim($result);
+          $after_case     = true;
           if (!$in_case) {
             $in_case = true;
             // Add a line break between cases.
             if (substr($result, -1) != '{') {
-              $result .= coder_br();
+              coder_br($result);
             }
           }
           else {
             // Decrease current indent to align multiple cases.
             --$_coder_indent;
           }
-          $result .= coder_br() . trim($text) .' ';
+          coder_br($result);
+          $result .= trim($text) .' ';
           break;
-        
+
         case T_BREAK:
           // Write break to a new line.
-          $result = rtrim($result) . coder_br() . trim($text);
+          $result = rtrim($result);
+          coder_br($result);
+          $result .= trim($text);
           if ($in_case && !$braces_in_case) {
             --$_coder_indent;
             $in_case = false;
           }
           break;
-        
+
         case T_RETURN:
         case T_CONTINUE:
           coder_add_space($result);
@@ -544,23 +659,39 @@ function coder_format_string($code = '')
             $in_case = false;
           }
           break;
-        
+
+        case T_ABSTRACT:
+        case T_PRIVATE:
+        case T_PUBLIC:
+        case T_PROTECTED:
+          // Class member function properties must be treated similar to
+          // T_FUNCTION, but without line-break after the token. Because more
+          // than one of these tokens can appear in front of a function token,
+          // we need another white-space control variable.
+          coder_br($result);
+          $result .= trim($text) .' ';
+          break;
+          
         case T_FUNCTION:
+          $in_function_declaration = true;
+          // Fall through.
         case T_CLASS:
           // Write function and class to new lines.
           $result = rtrim($result);
           if (substr($result, -1) == '}') {
-            $result .= coder_br();
+            coder_br($result);
           }
-          $result .= coder_br() . trim($text) .' ';
+          coder_br($result);
+          $result .= trim($text) .' ';
           break;
-        
+
         case T_EXTENDS:
-          // Add space before and after 'extends'.
+        case T_INSTANCEOF:
+          // Add space before and after 'extends' and 'instanceof'.
           $result = rtrim($result);
           $result .= ' '. trim($text) .' ';
           break;
-        
+
         case T_AND_EQUAL:
         case T_AS:
         case T_BOOLEAN_AND:
@@ -594,76 +725,96 @@ function coder_format_string($code = '')
           }
           $result .= trim($text) .' ';
           break;
-        
+
         case T_COMMENT:
         case T_ML_COMMENT:
         case T_DOC_COMMENT:
           if (substr($text, 0, 3) == '/**') {
             // Prepend a new line.
-            $result = rtrim($result) . coder_br() . coder_br();
-            
+            $result = rtrim($result);
+            coder_br($result);
+            coder_br($result);
+
             // Remove carriage returns.
             $text = str_replace("\r", '', $text);
-            
+
             $lines = explode("\n", $text);
             $params_fixed = false;
             for ($l = 0; $l < count($lines); ++$l) {
               $lines[$l] = trim($lines[$l]);
-              
+
               // Add a new line between function description and first parameter description.
               if (!$params_fixed && substr($lines[$l], 0, 8) == '* @param' && $lines[$l - 1] != '*') {
-                $result .= ' *'. coder_br();
+                $result .= ' *';
+                coder_br($result);
                 $params_fixed = true;
               }
               else if (!$params_fixed && substr($lines[$l], 0, 8) == '* @param') {
                 // Do nothing if parameter description is properly formatted.
                 $params_fixed = true;
               }
-              
+
               // Add a new line between function params and return.
               if (substr($lines[$l], 0, 9) == '* @return' && $lines[$l - 1] != '*') {
-                $result .= ' *'. coder_br();
+                $result .= ' *';
+                coder_br($result);
               }
-              
+
               // Add one space indent to get ' *[...]'.
               if ($l > 0) {
                 $result .= ' ';
               }
               $result .= $lines[$l];
               if ($l < count($lines)) {
-                $result .= coder_br();
+                coder_br($result);
               }
             }
           }
           else {
+            // Move the comment above if it's embedded.
+            $statement = false;
+            if ($after_semicolon && !$after_case) {
+              $nl_position     = strrpos(rtrim($result, " \n"), "\n");
+              $statement       = substr($result, $nl_position);
+              $result          = substr($result, 0, $nl_position);
+              $after_semicolon = false;
+              coder_br($result);
+            }
             $result .= trim($text);
             if ($parenthesis) {
               // Add extra indent for each parenthesis in multiline definitions (f.e. arrays).
               $_coder_indent = $_coder_indent + $parenthesis;
-              $result = rtrim($result) . coder_br();
+              $result = rtrim($result);
+              coder_br($result);
               $_coder_indent = $_coder_indent - $parenthesis;
             }
             else {
               // Discard any whitespace, just insert a line break.
-              $result .= coder_br();
+              coder_br($result);
+            }
+            if ($statement) {
+              $result = rtrim($result, "\n ");
+              $result .= $statement;
             }
           }
           break;
-        
+
         case T_INLINE_HTML:
           $result .= $text;
           break;
-        
+
         case T_START_HEREDOC:
-          $result .= trim($text) . coder_br(false);
+          $result .= trim($text);
+          coder_br($result, false);
           $in_heredoc = true;
           break;
-        
+
         case T_END_HEREDOC:
-          $result .= trim($text) . coder_br(false);
+          $result .= trim($text);
+          coder_br($result, false);
           $in_heredoc = false;
           break;
-        
+
         default:
           $result .= trim($text);
           break;
@@ -679,29 +830,46 @@ function coder_format_string($code = '')
 /**
  * Generate a line feed including current line indent.
  *
+ * This function will also remove all line indentation from the
+ * previous line if no text was added.
+ *
+ * @param &$result
+ *   Result variable to append break and indent to, passed by reference.
  * @param $add_indent
  *   Whether to add current line indent after line feed.
- * @return
- *   The resulting string.
  */
-function coder_br($add_indent = true) {
+function coder_br(&$result, $add_indent = true) {
   global $_coder_indent;
-  
+
+  // Scan result backwards for whitespace.
+  for ($i = strlen($result) - 1; $i >= 0; $i--) {
+    if ($result[$i] == ' ') {
+      continue;
+    }
+    if ($result[$i] == "\n") {
+      $result = rtrim($result, ' ');
+      break;
+    }
+    // Non-whitespace was encountered, no changes necessary.
+    break;
+  }
+
   $output = "\n";
   if ($add_indent && $_coder_indent >= 0) {
     $output .= str_repeat('  ', $_coder_indent);
   }
-  return $output;
+  $result .= $output;
 }
 
 /**
  * Write a space in certain conditions.
- * 
+ *
  * A conditional space is needed after a right parenthesis of an if statement
  * that is not followed by curly braces.
- * 
+ *
  * @param $result
  *   Current result string that will be checked.
+ *
  * @return
  *   Resulting string with or without an additional space.
  */
@@ -720,21 +888,21 @@ function coder_add_space(&$result) {
 function coder_trim_php($code) {
   // Remove surrounding whitespace.
   $code = trim($code);
-  
+
   // Insert CVS keyword Id.
   // Search in the very first 1000 chars, insert only one instance.
   if (strpos(substr($code, 0, 1000), '$Id') === false) {
     $code = preg_replace('/<\?php\n/', "<?php\n// \$Id\$\n\n", $code, 1);
   }
-  
+
   // Remove closing PHP tag.
   if (substr($code, -2) == '?>') {
     $code = rtrim($code, '?>');
   }
-  
+
   // Append two empty lines.
   $code .= str_repeat(chr(10), 2);
-  
+
   return $code;
 }
 
@@ -803,7 +971,7 @@ function coder_exec_processors($code, $p
       $code = preg_replace($task['#search'], $task['#replace'], $code);
     }
   }
-  
+
   return $code;
 }
 
@@ -843,36 +1011,6 @@ function coder_preprocessor_line_breaks_
   );
 }
 
-function coder_preprocessor_ml_array_add_comma() {
-  // @bug coder.module:1010.
-  return array(
-    '#title' => 'Append a comma to the last value of multiline arrays.',
-    // ^[\040\t]*(?!\*|\/\/)[^\*\/\n]*? matches anything in front of array, but not comments.
-    // \sarray\( prevents matching of in_array() and function calls.
-    // (\n|(?X>!\);).+?,?\n) matches a line break or the first array item.
-    // (.*?[^,;]) matches the rest array items.
-    // ,?(\n\s*)\); matches the end of multiline array, optionally including a comma.
-    '#search' => '/(^[\040\t]*(?!\*|\/\/)[^\*\/\n]*?\sarray\()(\n|(?>!\);).+?,?\n)(.*?[^,;]),?(\n\s*\);)/ism',
-    '#replace' => '$1$2$3,$4',
-    //'#debug' => true,
-  );
-}
-
-function coder_preprocessor_inline_comment() {
-  return array(
-    '#title' => 'Move inline comments above remarked line.',
-    '#weight' => 2,
-    // [\040\t] matches only a space or tab.
-    // (?!case) prevents matching of case statements.
-    // \S prevents matching of lines containing only a comment.
-    // [^:] prevents matching of URL protocols.
-    // [^;\$] prevents matching of CVS keyword Id comment and double slashes.
-    //   in quotes (f.e. "W3C//DTD").
-    '#search' => '@^([\040\t]*)(?!case)(\S.+?)[\040\t]*[^:]//\s*([^;\$]+?)$@m',
-    '#replace' => "$1// $3\n$1$2",
-  );
-}
-
 function coder_preprocessor_php() {
   return array(
     '#title' => 'Always use &lt;?php ?&gt; to delimit PHP code, not the &lt;? ?&gt; shorthands.',
@@ -909,10 +1047,10 @@ function coder_postprocessor_multiple_va
   // @todo Prevent matching of multiple lines separated by a blank line 26/03/2007 sun.
   return array(
     '#title' => 'Align equal signs of multiple variable assignments in the same column.',
-    // \s* matches whitespace including new lines.
+    // \n? * matches whitespace, but only one new line.
     // \$.+? matches variable names.
     // {3,} requires the pattern to match at least 3 times.
-    '#search' => '/^(\s*\$.+? = .+?$){3,}/m',
+    '#search' => '/^(\n? *\$.+? = .+?$){3,}/m',
     '#replace_callback' => 'coder_replace_multiple_vars',
   );
 }
@@ -920,7 +1058,7 @@ function coder_postprocessor_multiple_va
 function coder_replace_multiple_vars($matches) {
   // Retrieve all variable name = variable value pairs.
   preg_match_all('/^(\s*)(\$.+?) (.?)= (.+?$)/m', $matches[0], $vars, PREG_SET_ORDER);
-  
+
   // Determine the longest variable name.
   $maxlength = 0;
   foreach ($vars as $var) {
@@ -928,7 +1066,7 @@ function coder_replace_multiple_vars($ma
       $maxlength = strlen($var[2] . $var[3]);
     }
   }
-  
+
   // Realign variable values at the longest variable names.
   $return = '';
   $extra_spaces = 0;
@@ -944,7 +1082,66 @@ function coder_replace_multiple_vars($ma
       $return .= "\n";
     }
   }
-  
+
+  return $return;
+}
+
+function coder_postprocessor_indent_multiline_array() {
+  // Still buggy, disabled for now.
+  return array(
+    '#title' => 'Align equal signs of multiline array assignments in the same column.',
+    // ?: prevents capturing
+    // \s* initial whitespace
+    // ([\'"]).+?\1 matches a string key
+    // .+? matches any other key w/o whitespace
+    // \s*=>\s* matches associative array arrow syntax
+    // .+? matches value
+    '#search' => '/^(?:\s*(?:(?:([\'"]).+?\1|.+?)\s*=>\s*.+?|\),\s?)$){3,}/mi',
+    //'#replace_callback' => 'coder_replace_indent_multiline_array',
+  );
+}
+
+function coder_replace_indent_multiline_array($matches) {
+  // Separate out important components of the multiline array:
+  // (\s*) matches existing indent as \1
+  // (([\'"]).+?\2|\$.+?|[+\-]?(?:0x)?[0-9A-F]+) matches key as \2
+  //    ([\'"]).+?\3 matches a quoted key, quote used is \3
+  //    \.+? matches anything else
+  // \),\s*? matches a closing parenthesis in a nested array
+  // \s*=>\s* matches existing indentation and arrow to be discarded
+  // (.+?) matches value as \4
+  // {3,} requires three or more of these lines
+  // mi enables multiline and caseless mode
+  preg_match_all('/^(\s*)(?:(([\'"]).+?\3|\.+?)\s*=>\s*(.+?),?|\),)\s*?$/mi', $matches[0], $vars, PREG_SET_ORDER);
+  // Determine max key length for varying indentations.
+  $maxlengths = array();
+  foreach ($vars as $var) {
+    list(, $indent, $key) = $var;
+    if (!isset($maxlengths[$indent])) {
+      $maxlengths[$indent] = 0;
+    }
+    if (($t = strlen($key)) > $maxlengths[$indent]) {
+      $maxlengths[$indent] = $t;
+    }
+  }
+  // Reconstruct variable array declaration.
+  $return = '';
+  foreach ($vars as $var) {
+    list(, $indent, $key, , $value) = $var;
+    if ($key === null) {
+      $return .= "$indent),\n";
+      continue;
+    }
+    $spaces = str_repeat(' ', $maxlengths[$indent] - strlen($key));
+    if ($value !== 'array(') {
+      $comma = ',';
+    }
+    else {
+      $comma = '';
+    }
+    $return .= "$indent$key$spaces => $value$comma\n";
+  }
+  $return = rtrim($return, "\n");
   return $return;
 }
 
@@ -966,7 +1163,7 @@ function coder_postprocessor_array_rearr
 function coder_replace_array_rearrange($matches) {
   // Retrieve all array items, except the last one.
   preg_match_all('/(.+? => .+?,) /', $matches[3], $items);
-  
+
   // The original line including array(.
   $return = $matches[1] . $matches[2] ."\n";
   foreach ($items[1] as $item) {
@@ -977,7 +1174,7 @@ function coder_replace_array_rearrange($
   $return .= $matches[1] .'  '. $matches[5] .",\n";
   // Closing parenthesis (on a new line).
   $return .= $matches[1] .')';
-  
+
   return $return;
 }
 
Index: scripts/coder_format/tests/CoderTestFile.php
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/coder/scripts/coder_format/tests/Attic/CoderTestFile.php,v
retrieving revision 1.1.2.1
diff -u -p -r1.1.2.1 CoderTestFile.php
--- scripts/coder_format/tests/CoderTestFile.php	19 Jan 2008 19:21:16 -0000	1.1.2.1
+++ scripts/coder_format/tests/CoderTestFile.php	20 Jan 2008 18:58:02 -0000
@@ -13,39 +13,47 @@ class CoderTestFile extends SimpleExpect
   var $test;
 
   /* PHP to be parsed */
-  var $input = '';
+  var $input = array();
 
   /* Expected output */
-  var $expect = '';
+  var $expect = array();
 
   /* Actual result */
-  var $actual;
+  var $actual = array();
 
   /* Whether or not <?php and other stuff should be added */
-  var $full;
+  var $full = array();
 
   /**
    * Loads this class from a file.
    *
-   * @param $filename String filename to load
+   * @param string $filename
+   *   A filename to load.
    */
   function load($filename) {
     $this->filename = $filename;
     $fh             = fopen($filename, 'r');
     $state          = '';
     $php_stripped   = FALSE;
+    $line_no        = 0;
+    $unit           = 0;
     
     while (($line = fgets($fh)) !== false) {
       // Normalize newlines.
       $line = rtrim($line, "\n\r");
       // Strip first PHP tag, if existent.
-      if (!$php_stripped && strpos($line, '<?php') === 0) {
+      if (!$php_stripped && !$line_no && strpos($line, '<?php') === 0) {
         $php_stripped = TRUE;
         continue;
       }
+      // Detect INPUT and EXPECT sections.
       if (substr($line, 0, 2) == '--') {
-        // Detected section.
         $state = trim($line, ' -');
+        
+        // If a new INPUT section begins, start a new unit.
+        if ($state == 'INPUT') {
+          $unit++;
+        }
         continue;
       }
       if (!$state) {
@@ -55,31 +63,35 @@ class CoderTestFile extends SimpleExpect
         $key = $state;
       }
       switch ($key) {
-        case 'INPUT':
-          $this->input .= $line ."\n";
+        case 'TEST':
+          $this->test = $line;
           break;
 
-        case 'EXPECT':
-          $this->expect .= $line ."\n";
+        case 'FULL':
+          $this->full[$unit] = (bool)$line;
           break;
 
-        case 'TEST':
-          $this->test = $line;
+        case 'INPUT':
+          $this->input[$unit] .= $line ."\n";
           break;
 
-        case 'FULL':
-          $this->full = (bool)$line;
+        case 'EXPECT':
+          $this->expect[$unit] .= $line ."\n";
           break;
       }
     }
     fclose($fh);
-    if ($this->expect === '') {
-      $this->expect = $this->input;
-    }
-    if (!$this->full) {
-      $prepend      = "<?php\n//$". "Id$\n\n";
-      $this->input  = $prepend . trim($this->input, "\n") ."\n\n";
-      $this->expect = $prepend . trim($this->expect, "\n") ."\n\n";
+    foreach (range(1, $unit) as $unit) {
+      // If no EXPECTed code was defined, INPUT shouldn't be altered.
+      if (!isset($this->expect[$unit])) {
+        $this->expect[$unit] = $this->input[$unit];
+      }
+      // If FULL was not defined, add a PHP header to contents.
+      if (!$this->full[$unit]) {
+        $prepend             = "<?php\n// $". "Id$\n\n";
+        $this->input[$unit]  = $prepend . rtrim($this->input[$unit], "\n") ."\n\n";
+        $this->expect[$unit] = $prepend . rtrim($this->expect[$unit], "\n") ."\n\n";
+      }
     }
   }
 
@@ -92,16 +104,28 @@ class CoderTestFile extends SimpleExpect
     if ($filename) {
       $this->load($filename);
     }
-    $this->actual = coder_format_string_all($this->input);
     
-    return $this->expect === $this->actual;
+    // Perform test.
+    // Test passes until proven invalid.
+    $valid = TRUE;
+    foreach ($this->input as $unit => $content) {
+      // Parse input and store results.
+      $this->actual[$unit] = coder_format_string_all($this->input[$unit]);
+      
+      // Let this test fail, if a unit fails.
+      if ($this->expect[$unit] !== $this->actual[$unit]) {
+        $valid = FALSE;
+      }
+    }
+    
+    return $valid;
   }
 
   /**
    * Implements SimpleExpectation::testMessage().
    */
   function testMessage() {
-    $message = $this->test .' test at '. htmlspecialchars($this->filename);
+    $message = $this->test .' test in '. htmlspecialchars(basename($this->filename));
     return $message;
   }
 
@@ -111,13 +135,18 @@ class CoderTestFile extends SimpleExpect
   function render() {
     drupal_add_css(drupal_get_path('module', 'coder') .'/scripts/coder_format/tests/coder-diff.css', 'module', 'all', false);
     
-    $diff     = new Text_Diff('auto', array(explode("\n", $this->expect), explode("\n", $this->actual)));
-    $renderer = new Text_Diff_Renderer_parallel($this->test .' test at '. htmlspecialchars($this->filename));
-    
-    $renderer->original = 'Expected';
-    $renderer->final    = 'Actual';
+    foreach ($this->input as $unit => $content) {
+      // Do not output passed units.
+      if ($this->expect[$unit] === $this->actual[$unit]) {
+        continue;
+      }
+      
+      $diff     = new Text_Diff('auto', array(explode("\n", $this->expect[$unit]), explode("\n", $this->actual[$unit])));
+      $renderer = new Text_Diff_Renderer_parallel($this->test .' test in '. htmlspecialchars(basename($this->filename)));
+      
+      $message .= $renderer->render($diff);
+    }
     
-    $message .= $renderer->render($diff);
     return $message;
   }
 }
@@ -128,11 +157,12 @@ class CoderTestFile extends SimpleExpect
  */
 class Text_Diff_Renderer_parallel extends Text_Diff_Renderer {
   /* String header for left column */
-  var $original = 'Original';
+  var $original = 'Expected';
 
   /* String header for right column */
-  var $final = 'Final';
-  // these are big to ensure entire string is output
+  var $final = 'Actual';
+  
+  // These are big to ensure entire string is output.
   var $_leading_context_lines  = 10000;
   var $_trailing_context_lines = 10000;
   var $title;
Index: scripts/coder_format/tests/all.test
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/coder/scripts/coder_format/tests/Attic/all.test,v
retrieving revision 1.1.2.1
diff -u -p -r1.1.2.1 all.test
--- scripts/coder_format/tests/all.test	19 Jan 2008 19:21:16 -0000	1.1.2.1
+++ scripts/coder_format/tests/all.test	20 Jan 2008 19:58:23 -0000
@@ -25,11 +25,14 @@ class CoderFormatTest extends CoderTestC
   function test() {
     $dir   = drupal_get_path('module', 'coder') .'/scripts/coder_format/tests/tests';
     $files = array_keys(file_scan_directory($dir, '\.phpt$'));
+    // Order tests alphabetically, but use a weight > 0 to append them after
+    // overall test results.
+    $c = 10;
     foreach ($files as $file) {
       $expectation = new CoderTestFile();
       $result = $this->assert($expectation, $file, '%s');
       if (!$result) {
-        echo $expectation->render();
+        $this->_reporter->writeContent($expectation->render(), $c++);
       }
     }
   }
Index: scripts/coder_format/tests/coder-diff.css
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/coder/scripts/coder_format/tests/Attic/coder-diff.css,v
retrieving revision 1.1.2.1
diff -u -p -r1.1.2.1 coder-diff.css
--- scripts/coder_format/tests/coder-diff.css	19 Jan 2008 19:21:16 -0000	1.1.2.1
+++ scripts/coder_format/tests/coder-diff.css	20 Jan 2008 18:57:15 -0000
@@ -1,9 +1,5 @@
 /* $Id: coder-diff.css,v 1.1.2.1 2008/01/19 19:21:16 sun Exp $ */
 
-.diff {
-  margin: 5%;
-  width: 87%;
-}
 .diff th {
   width: 50%;
 }
Index: scripts/coder_format/tests/tests/br.phpt
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/coder/scripts/coder_format/tests/tests/Attic/br.phpt,v
retrieving revision 1.1.2.1
diff -u -p -r1.1.2.1 br.phpt
--- scripts/coder_format/tests/tests/br.phpt	19 Jan 2008 20:15:21 -0000	1.1.2.1
+++ scripts/coder_format/tests/tests/br.phpt	20 Jan 2008 17:34:26 -0000
@@ -2,31 +2,23 @@
 TEST: Blank lines with whitespace
 
 --INPUT--
-// Change:
 if ($foo) {
   bar();
   
   baz();
 }
 
-// No change:
-if ($foo) {
-  bar();
-
-  baz();
-}
-
 --EXPECT--
-// Change:
 if ($foo) {
   bar();
 
   baz();
 }
 
-// No change:
+--INPUT--
 if ($foo) {
   bar();
 
   baz();
 }
+
Index: scripts/coder_format/tests/tests/comments.phpt
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/coder/scripts/coder_format/tests/tests/Attic/comments.phpt,v
retrieving revision 1.1.2.1
diff -u -p -r1.1.2.1 comments.phpt
--- scripts/coder_format/tests/tests/comments.phpt	19 Jan 2008 20:15:21 -0000	1.1.2.1
+++ scripts/coder_format/tests/tests/comments.phpt	20 Jan 2008 17:52:11 -0000
@@ -2,30 +2,12 @@
 TEST: Comment movement
 
 --INPUT--
-// Change:
 $foo = foo(); // Move up.
 if ($foo) {
   bar($foo); // Move up.
 }
 
-// Don't change:
-$string = '//';
-$foo    = 'http://google.com';
-$string = array(
-  'foo', '//',
-);
-
-// Comment // comment.
-
-/**
- * This does stuff with FOO//BOO.
- */
-function foo() {
-  return 'boo';
-}
-
 --EXPECT--
-// Change:
 // Move up.
 $foo = foo();
 if ($foo) {
@@ -33,18 +15,164 @@ if ($foo) {
   bar($foo);
 }
 
-// Don't change:
+--INPUT--
 $string = '//';
 $foo    = 'http://google.com';
 $string = array(
   'foo', '//',
 );
 
+--INPUT--
 // Comment // comment.
 
+--INPUT--
+
 /**
  * This does stuff with FOO//BOO.
  */
 function foo() {
   return 'boo';
 }
+
+--INPUT--
+function _batch_progress_page_nojs() {
+  // This is one of the later requests: do some processing first.
+
+  // Error handling: if PHP dies due to a fatal error (e.g. non-existant
+  // function), it will output whatever is in the output buffer,
+  // followed by the error message.
+}
+
+--INPUT--
+function drupal_page_cache_header($cache) {
+  if ($if_modified_since && $if_none_match
+      && $if_none_match == $etag // etag must match
+      && $if_modified_since == $last_modified) {  // if-modified-since must match
+    exit();
+  }
+}
+
+--EXPECT--
+function drupal_page_cache_header($cache) {
+  if ($if_modified_since && $if_none_match
+    // etag must match
+    && $if_none_match == $etag
+    // if-modified-since must match
+    && $if_modified_since == $last_modified) {
+    exit();
+  }
+}
+
+--INPUT--
+function parse_size($size) {
+  $suffixes = array(
+    '' => 1,
+    'k' => 1024,
+    'm' => 1048576, // 1024 * 1024
+    'g' => 1073741824, // 1024 * 1024 * 1024
+  );
+}
+
+--EXPECT--
+function parse_size($size) {
+  $suffixes = array(
+    '' => 1,
+    'k' => 1024,
+    // 1024 * 1024
+    'm' => 1048576,
+    // 1024 * 1024 * 1024
+    'g' => 1073741824,
+  );
+}
+
+--INPUT--
+function drupal_to_js($var) {
+  switch ($foo) {
+    case 'boolean':
+      return $var ? 'true' : 'false'; // Lowercase necessary!
+  }
+}
+
+--EXPECT--
+function drupal_to_js($var) {
+  switch ($foo) {
+    case 'boolean':
+      // Lowercase necessary!
+      return $var ? 'true' : 'false';
+  }
+}
+
+--INPUT--
+function _db_query_callback($match, $init = FALSE) {
+  switch ($match[1]) {
+    case '%d': // We must use type casting to int to convert FALSE/NULL/(TRUE?)
+      return (int)array_shift($args); // We don't need db_escape_string as numbers are db-safe
+
+    case '%b': // binary data
+      return db_encode_blob(array_shift($args));
+  }
+}
+
+--EXPECT--
+function _db_query_callback($match, $init = FALSE) {
+  switch ($match[1]) {
+    case '%d':
+      // We must use type casting to int to convert FALSE/NULL/(TRUE?)
+      // We don't need db_escape_string as numbers are db-safe
+      return (int)array_shift($args);
+
+    case '%b':
+      // binary data
+      return db_encode_blob(array_shift($args));
+  }
+}
+
+--INPUT--
+function _locale_import_read_po($op, $file, $mode = NULL, $lang = NULL, $group = 'default') {
+  $context = "COMMENT"; // Parser context: COMMENT, MSGID, MSGID_PLURAL, MSGSTR and MSGSTR_ARR
+  $lineno = 0;          // Current line
+
+  while (!feof($fd)) {
+    $line = fgets($fd, 1024); // A line should not be this long
+    if (!strncmp("#", $line, 1)) { // A comment
+      if ($context == "COMMENT") { // Already in comment context: add
+        $current["#"][] = substr($line, 1);
+      }
+      elseif (($context == "MSGSTR") || ($context == "MSGSTR_ARR")) { // End current entry, start a new one
+        _locale_import_one_string($op, $current, $mode, $lang, $file, $group);
+      }
+      else { // Parse error
+        return FALSE;
+      }
+    }
+  }
+}
+
+--EXPECT--
+function _locale_import_read_po($op, $file, $mode = NULL, $lang = NULL, $group = 'default') {
+  // Parser context: COMMENT, MSGID, MSGID_PLURAL, MSGSTR and MSGSTR_ARR
+  $context = "COMMENT";
+  // Current line
+  $lineno = 0;
+
+  while (!feof($fd)) {
+    // A line should not be this long
+    $line = fgets($fd, 1024);
+    // A comment
+    if (!strncmp("#", $line, 1)) {
+      // Already in comment context: add
+      if ($context == "COMMENT") {
+        $current["#"][] = substr($line, 1);
+      }
+      // End current entry, start a new one
+      elseif (($context == "MSGSTR") || ($context == "MSGSTR_ARR")) {
+        _locale_import_one_string($op, $current, $mode, $lang, $file, $group);
+      }
+      // Parse error
+      else {
+        return FALSE;
+      }
+    }
+  }
+}
+
Index: scripts/coder_format/tests/tests/control.phpt
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/coder/scripts/coder_format/tests/tests/Attic/control.phpt,v
retrieving revision 1.1.2.1
diff -u -p -r1.1.2.1 control.phpt
--- scripts/coder_format/tests/tests/control.phpt	19 Jan 2008 20:15:21 -0000	1.1.2.1
+++ scripts/coder_format/tests/tests/control.phpt	20 Jan 2008 17:56:14 -0000
@@ -2,17 +2,14 @@
 TEST: Control structures
 
 --INPUT--
-// No change:
 function menu_tree_page_data($menu_name = 'navigation') {
   // Check whether the current menu has any links set to be expanded.
   if (in_array($menu_name, $expanded)) {
     // Collect all the links set to be expanded, and then add all of
     // their children to the list as well.
     do {
-      $result = db_query("SELECT mlid FROM {menu_links} WHERE menu_name = '%s' AND expanded = 1 AND has_children = 1 AND plid IN (". $placeholders .') AND mlid NOT IN ('. $placeholders .')', array_merge(array($menu_name), $args, $args));
-      $num_rows = FALSE;
+      $result = db_query();
       while ($item = db_fetch_array($result)) {
-        $args[] = $item['mlid'];
         $num_rows = TRUE;
       }
       $placeholders = implode(', ', array_fill(0, count($args), '%d'));
@@ -20,23 +17,47 @@ function menu_tree_page_data($menu_name 
   }
 }
 
+--INPUT--
+function format_case() {
+  switch ($moo) {
+    case 'foo':
+      $bar = $baz;
+      break;
 
---EXPECT--
-// No change:
-function menu_tree_page_data($menu_name = 'navigation') {
-  // Check whether the current menu has any links set to be expanded.
-  if (in_array($menu_name, $expanded)) {
-    // Collect all the links set to be expanded, and then add all of
-    // their children to the list as well.
-    do {
-      $result   = db_query("SELECT mlid FROM {menu_links} WHERE menu_name = '%s' AND expanded = 1 AND has_children = 1 AND plid IN (". $placeholders .') AND mlid NOT IN ('. $placeholders .')', array_merge(array($menu_name), $args, $args));
-      $num_rows = FALSE;
-      while ($item = db_fetch_array($result)) {
-        $args[]   = $item['mlid'];
-        $num_rows = TRUE;
+    case 'fee':
+    default:
+      $bar = $bay;
+      return;
+  }
+}
+
+--INPUT--
+function case_return() {
+  switch ($moo) {
+    case 'foo':
+      if ($bar) {
+        return $baz;
       }
-      $placeholders = implode(', ', array_fill(0, count($args), '%d'));
-    } while ($num_rows);
+      $baz = $bar;
+      break;
+
+    case 'fee':
+      $bar = $bay;
+      return;
+  }
+}
+
+--INPUT--
+function language_url_rewrite(&$path, &$options) {
+  switch (variable_get('language_negotiation', LANGUAGE_NEGOTIATION_NONE)) {
+    case LANGUAGE_NEGOTIATION_PATH_DEFAULT:
+      $default = language_default();
+      // Intentionally no break here.
+    case LANGUAGE_NEGOTIATION_PATH:
+      if (!empty($options['language']->prefix)) {
+        $options['prefix'] = $options['language']->prefix .'/';
+      }
+      break;
   }
 }
 
Index: scripts/coder_format/tests/tests/misc.phpt
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/coder/scripts/coder_format/tests/tests/Attic/misc.phpt,v
retrieving revision 1.1.2.1
diff -u -p -r1.1.2.1 misc.phpt
--- scripts/coder_format/tests/tests/misc.phpt	19 Jan 2008 20:15:21 -0000	1.1.2.1
+++ scripts/coder_format/tests/tests/misc.phpt	20 Jan 2008 17:56:58 -0000
@@ -2,25 +2,14 @@
 TEST: Miscellaneous (split me!)
 
 --INPUT--
-// No change:
 if ($foo) {
   if ($bar) {
     // Trall!
   }
 }
 
+--INPUT--
 foo(
   $bar
 );
 
---EXPECT--
-// No change:
-if ($foo) {
-  if ($bar) {
-    // Trall!
-  }
-}
-
-foo(
-  $bar
-);
Index: scripts/coder_format/tests/tests/ml_array.phpt
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/coder/scripts/coder_format/tests/tests/Attic/ml_array.phpt,v
retrieving revision 1.1.2.1
diff -u -p -r1.1.2.1 ml_array.phpt
--- scripts/coder_format/tests/tests/ml_array.phpt	19 Jan 2008 20:15:21 -0000	1.1.2.1
+++ scripts/coder_format/tests/tests/ml_array.phpt	20 Jan 2008 18:04:13 -0000
@@ -1,7 +1,7 @@
 <?php
 TEST: Multiline arrays
 
--- INPUT --
+--INPUT--
 $var = array(
   'install_page' => array(
     'arguments' => array(
@@ -9,6 +9,16 @@ $var = array(
   ),
 );
 
+--EXPECT--
+$var = array(
+  'install_page' => array(
+    'arguments' => array(
+      'content' => NULL,
+    ),
+  ),
+);
+
+--INPUT--
 $array = array(
   'foo' => 'bar',
   2 => $foo,
@@ -17,6 +27,7 @@ $array = array(
   $bar => 'asdf',
 );
 
+--INPUT--
 $deep = array(
   'foo' => array(
     'croon' => 'asdf',
@@ -28,11 +39,32 @@ $deep = array(
   )
 );
 
+--EXPECT--
+$deep = array(
+  'foo' => array(
+    'croon' => 'asdf',
+    'f' => 'a',
+  ),
+  'barasdfsadf' => array(
+    'asdfasdfasdf' => 'd',
+    'fsd' => 23,
+  ),
+);
+
+--INPUT--
 drupal_add_link(array('rel' => 'alternate',
                       'type' => 'application/rss+xml',
                       'title' => $title,
                       'href' => $url));
 
+--EXPECT--
+drupal_add_link(array('rel' => 'alternate',
+    'type' => 'application/rss+xml',
+    'title' => $title,
+    'href' => $url,
+  ));
+
+--INPUT--
 function node_theme() {
   return array(
     'node' => array(
@@ -45,68 +77,22 @@ function node_theme() {
     'node_search_admin' => array(
       'arguments' => array('form' => NULL),
     ),
-    'node_filter_form' => array(
-      'arguments' => array('form' => NULL),
-      'file' => 'node.admin.inc',
-    ),
     'node_filters' => array(
       'arguments' => array('form' => NULL),
       'file' => 'node.admin.inc'
     ),
-    'node_admin_nodes' => array(
-      'arguments' => array('form' => NULL),
-      'file' => 'node.admin.inc',
-    ),
-    'node_add_list' => array('arguments' => array('content' => NULL),
-      'file' => 'node.pages.inc',
-    ),
     'node_form' => array(
-      'arguments' => array('form' => NULL),
+      'arguments' => 123,
       'file' => 'node.pages.inc',
     ),
     'node_preview' => array('arguments' => array('node' => NULL), 'file' => 'node.pages.inc'),
     'node_log_message' => array(
-      'arguments' => array('log' => NULL),
-    ),
-    'node_submitted' => array(
-      'arguments' => array('node' => NULL),
-    ),
+      'arguments' => array('log' => NULL)
+    )
   );
 }
 
 -- EXPECT --
-$var = array(
-  'install_page' => array(
-    'arguments' => array(
-      'content' => NULL,
-    ),
-  ),
-);
-
-$array = array(
-  'foo' => 'bar',
-  2 => $foo,
-  0x000000 => 'asdf',
-  "CRIVENS" => 3,
-  $bar => 'asdf',
-);
-
-$deep = array(
-  'foo' => array(
-    'croon' => 'asdf',
-    'f' => 'a',
-  ),
-  'barasdfsadf' => array(
-    'asdfasdfasdf' => 'd',
-    'fsd' => 23,
-  ),
-);
-
-drupal_add_link(array('rel' => 'alternate',
-    'type' => 'application/rss+xml',
-    'title' => $title,
-    'href' => $url,
-  ));
 function node_theme() {
   return array(
     'node' => array(
@@ -119,32 +105,18 @@ function node_theme() {
     'node_search_admin' => array(
       'arguments' => array('form' => NULL),
     ),
-    'node_filter_form' => array(
-      'arguments' => array('form' => NULL),
-      'file' => 'node.admin.inc',
-    ),
     'node_filters' => array(
       'arguments' => array('form' => NULL),
       'file' => 'node.admin.inc',
     ),
-    'node_admin_nodes' => array(
-      'arguments' => array('form' => NULL),
-      'file' => 'node.admin.inc',
-    ),
-    'node_add_list' => array('arguments' => array('content' => NULL),
-      'file' => 'node.pages.inc',
-    ),
     'node_form' => array(
-      'arguments' => array('form' => NULL),
+      'arguments' => 123,
       'file' => 'node.pages.inc',
     ),
     'node_preview' => array('arguments' => array('node' => NULL), 'file' => 'node.pages.inc'),
     'node_log_message' => array(
       'arguments' => array('log' => NULL),
     ),
-    'node_submitted' => array(
-      'arguments' => array('node' => NULL),
-    ),
   );
 }
 
Index: scripts/coder_format/tests/tests/operators.phpt
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/coder/scripts/coder_format/tests/tests/Attic/operators.phpt,v
retrieving revision 1.1.2.1
diff -u -p -r1.1.2.1 operators.phpt
--- scripts/coder_format/tests/tests/operators.phpt	19 Jan 2008 20:15:21 -0000	1.1.2.1
+++ scripts/coder_format/tests/tests/operators.phpt	20 Jan 2008 18:43:05 -0000
@@ -1,31 +1,105 @@
 <?php
-TEST: Arithmetic operators
+TEST: Operators
 
 --INPUT--
-// No change:
 function foo() {
   $foo = $bar ? -1 : 0;
   $foo = (-1 + 1);
   return ($a_weight < $b_weight) ? -1 : 1;
 }
 
+--INPUT--
 function file_download() {
   if (in_array(-1, $headers)) {
     return drupal_access_denied();
   }
 }
 
---EXPECT--
-// No change:
-function foo() {
-  $foo = $bar ? -1 : 0;
-  $foo = (-1 + 1);
-  return ($a_weight < $b_weight) ? -1 : 1;
-}
+--INPUT--
+$a = ($b = 4) + 5;
+--INPUT--
+$a = 3;
+--INPUT--
+$a += 5;
+--INPUT--
+$b = "Hello world";
+$b .= "foo";
+--INPUT--
+$c = $a + $b;
+$c = 1 + 2;
+--INPUT--
+$c = $a - $b;
+$c = 1 - 2;
+--INPUT--
+$c = $a * $b;
+$c = 1 * 2;
+--INPUT--
+$c = $a / $b;
+$c = 1 / 2;
+--INPUT--
+$c = $a % $b;
+$c = 1 % 2;
 
-function file_download() {
-  if (in_array(-1, $headers)) {
-    return drupal_access_denied();
-  }
+--INPUT--
+$c = $a & $b;
+$c = $a | $b;
+$c = $a ^ $b;
+$c = ~$a;
+$c = $a << $b;
+$c = $a >> $b;
+
+--INPUT--
+$c = $a == $b;
+$c = $a === $b;
+$c = $a != $b;
+$c = $a <> $b;
+$c = $a !== $b;
+$c = $a < $b;
+$c = $a > $b;
+$c = $a <= $b;
+$c = $a >= $b;
+
+--INPUT--
+$c = @imagettftext($file, $foo);
+
+--INPUT--
+$output = `ls -al`;
+
+--INPUT--
+$c = ++$a;
+$c = $a++;
+$c = --$a;
+$c = $a--;
+
+--INPUT--
+$c = $a and $b;
+$c = $a or $b;
+$c = $a xor $b;
+$c = !$a;
+$c = $a && $b;
+$c = $a || $b;
+
+--INPUT--
+$c = $a . $b;
+$c = $a .'foo';
+$c = 'foo'. $a;
+$c = 'foo'. $a . $b .'bar';
+$c = 'foo' . 'bar';
+
+--INPUT--
+$c = $a + $b;
+$c = $a == $b;
+$c = $a === $b;
+$c = $a != $b;
+$c = $a <> $b;
+$c = $a !== $b;
+
+--INPUT--
+class A {}
+
+$foo = new A;
+
+if ($foo instanceof A) {
+  return;
 }
 
Index: scripts/coder_format/tests/tests/parenthesis.phpt
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/coder/scripts/coder_format/tests/tests/Attic/parenthesis.phpt,v
retrieving revision 1.1.2.1
diff -u -p -r1.1.2.1 parenthesis.phpt
--- scripts/coder_format/tests/tests/parenthesis.phpt	19 Jan 2008 20:15:21 -0000	1.1.2.1
+++ scripts/coder_format/tests/tests/parenthesis.phpt	20 Jan 2008 18:10:21 -0000
@@ -2,29 +2,56 @@
 TEST: Parenthesis
 
 --INPUT--
-// No change:
 function drupal_mail_send($message) {
   return mail(
     $message['to'],
     mime_header_encode($message['subject']),
-    // Note: e-mail uses CRLF for line-endings, but PHP's API requires LF.
-    // They will appear correctly in the actual e-mail that is sent.
     str_replace("\r", '', $message['body']),
     join("\n", $mimeheaders)
   );
 }
 
+--INPUT--
+function drupal_to_js($var) {
+  switch (gettype($var)) {
+    case 'string':
+      return '"'. str_replace(array("\r", "\n", "<", ">", "&"),
+                              array('\r', '\n', '\x3c', '\x3e', '\x26'),
+                              addslashes($var)) .'"';
+    default:
+      return 'null';
+  }
+}
 
 --EXPECT--
-// No change:
-function drupal_mail_send($message) {
-  return mail(
-    $message['to'],
-    mime_header_encode($message['subject']),
-    // Note: e-mail uses CRLF for line-endings, but PHP's API requires LF.
-    // They will appear correctly in the actual e-mail that is sent.
-    str_replace("\r", '', $message['body']),
-    join("\n", $mimeheaders)
-  );
+function drupal_to_js($var) {
+  switch (gettype($var)) {
+    case 'string':
+      return '"'. str_replace(array("\r", "\n", "<", ">", "&"),
+        array('\r', '\n', '\x3c', '\x3e', '\x26'),
+        addslashes($var)) .'"';
+
+    default:
+      return 'null';
+  }
+}
+
+--INPUT--
+function drupal_urlencode($text) {
+  if (variable_get('clean_url', '0')) {
+    return str_replace(array('%2F', '%26', '%23', '//'),
+                       array('/', '%2526', '%2523', '/%252F'),
+                       rawurlencode($text));
+  }
+}
+
+--EXPECT--
+function drupal_urlencode($text) {
+  if (variable_get('clean_url', '0')) {
+    return str_replace(array('%2F', '%26', '%23', '//'),
+      array('/', '%2526', '%2523', '/%252F'),
+      rawurlencode($text)
+    );
+  }
 }
 
Index: scripts/coder_format/tests/tests/references.phpt
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/coder/scripts/coder_format/tests/tests/Attic/references.phpt,v
retrieving revision 1.1.2.1
diff -u -p -r1.1.2.1 references.phpt
--- scripts/coder_format/tests/tests/references.phpt	19 Jan 2008 20:15:21 -0000	1.1.2.1
+++ scripts/coder_format/tests/tests/references.phpt	20 Jan 2008 18:15:16 -0000
@@ -2,15 +2,25 @@
 TEST: Assignments by reference
 
 --INPUT--
-// No change:
 function &foo() {
-  echo 'asdf';
+  return;
 }
 
+--INPUT--
+function foo(&$node, $bar, $baz) {
+  return;
+}
 
---EXPECT--
-// No change:
-function &foo() {
-  echo 'asdf';
+--INPUT--
+function foo() {
+  $bar = &$baz;
+  return;
+}
+
+--INPUT--
+function foo($foo, $bar) {
+  if ($foo & $bar) {
+    return $bar = $baz;
+  }
 }
 
Index: scripts/coder_format/tests/tests/variables.phpt
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/coder/scripts/coder_format/tests/tests/Attic/variables.phpt,v
retrieving revision 1.1.2.1
diff -u -p -r1.1.2.1 variables.phpt
--- scripts/coder_format/tests/tests/variables.phpt	19 Jan 2008 20:15:21 -0000	1.1.2.1
+++ scripts/coder_format/tests/tests/variables.phpt	20 Jan 2008 19:54:59 -0000
@@ -2,47 +2,23 @@
 TEST: Variables
 
 --INPUT--
-// No change:
-function node_view($node, $teaser = FALSE, $page = FALSE, $links = TRUE) {
-  $node = (object)$node;
+function db_status_report($phase) {
+  $foo = bar();
+  $t   = get_t();
+  $baz = bay();
 
-  $node = node_build_content($node, $teaser, $page);
-
-  if ($links) {
-    $node->links = module_invoke_all('link', 'node', $node, $teaser);
-    drupal_alter('link', $node->links, $node);
-  }
-}
-
-function node_content_form($node, $form_state) {
-  $type = node_get_types('type', $node);
-  $form = array();
-
-  if ($type->has_title) {
-    $form['title'] = array();
-  }
+  $version = db_version();
 }
 
+--INPUT--
+class CoderTestFile extends SimpleExpectation {
+  private $expected;
 
---EXPECT--
-// No change:
-function node_view($node, $teaser = FALSE, $page = FALSE, $links = TRUE) {
-  $node = (object)$node;
-
-  $node = node_build_content($node, $teaser, $page);
-
-  if ($links) {
-    $node->links = module_invoke_all('link', 'node', $node, $teaser);
-    drupal_alter('link', $node->links, $node);
-  }
-}
-
-function node_content_form($node, $form_state) {
-  $type = node_get_types('type', $node);
-  $form = array();
+  /* Filename of test */
+  var $filename;
 
-  if ($type->has_title) {
-    $form['title'] = array();
+  protected function describeException($exception) {
+    return get_class($exception) .": ". $exception->getMessage();
   }
 }
 
