--- WADF.2.php	2008-06-25 10:59:57.000000000 +0100
+++ WADF.php	2008-06-26 17:17:45.000000000 +0100
@@ -22,13 +22,23 @@
  */
 class Tools_WADF {
 
-	const VCREFTYPE_REV = 'rev';
-	const VCREFTYPE_TAG = 'tag';
-	const VCREFTYPE_BRANCH = 'branch';
- 	const VCREFTYPE_TRUNK = 'trunk';
+	const VCREFTYPE_REV     = 'rev';
+	const VCREFTYPE_TAG     = 'tag';
+	const VCREFTYPE_BRANCH  = 'branch';
+ 	const VCREFTYPE_TRUNK   = 'trunk';
  	const VCREFTYPE_UNKNOWN = 'unknown';
+
+	const OUTPUT_SILENT     = 0;
+	const OUTPUT_NORMAL     = 50;
+	const OUTPUT_VERBOSE    = 100;
+
+	const DEBUG_GENERAL     = 10;
+	const DEBUG_ERROR       = 20;
+	const DEBUG_WARNING     = 40;
+	const DEBUG_INFORMATION = 60;
+	const DEBUG_VERBOSE     = 80;
  	
-	protected $_debug = 0;
+	protected $_debug = self::OUTPUT_NORMAL;
 
 	// the app reference
 	public $appref;
@@ -236,7 +246,7 @@
 					}
 				}
 				// TODO check host, user, pass, name are all non-empty
-				print "Setting up database $name on host $host...\n";
+				$this->_debugOutput( "Setting up database $name on host $host...", self::DEBUG_GENERAL);
 				$schema_path = "$dir/$schema";
 				if (file_exists($schema_path)) {
 					// FIXME abstract db-specific stuff
@@ -255,25 +265,25 @@
 						mysql_query("GRANT ALL on $name.* to $user IDENTIFIED BY '$pass'", $db);
 					}
 					if (in_array('schema', $deploy_options)) {
-						print "Deleting existing tables in database...\n";
+						$this->_debugOutput( "Deleting existing tables in database...", self::DEBUG_GENERAL);
 						mysql_select_db($name, $db);
 						$res = mysql_query('SHOW TABLES');
 						mysql_query('SET FOREIGN_KEY_CHECKS=0');
 						while ($table = mysql_fetch_row($res)) {
-							print "\tDropping table " . $table[0] . "\n"; 
+							$this->_debugOutput( "\tDropping table " . $table[0], self::DEBUG_GENERAL); 
 							mysql_query("DROP TABLE '" . $table[0] . "'", $db);
 						}
 						$cmd = "mysql $name -h $host -u $user ".(($pass != null) ? "-p$pass" : '')." < $dir/$schema";
 					}
 					mysql_close($db);
-					//print "$cmd\n";
+					//$this->_debugOutput( "$cmd");
 					exec($cmd);
 				} else {
 					die("ERROR: schema file $schema_path not found\n");
 				}
 			}
 		} else {
-			print "No database to deploy\n";
+			$this->_debugOutput( "No database to deploy", self::DEBUG_GENERAL);
 		}
 		
 	}
@@ -326,7 +336,7 @@
 	{
 		$crontab_file = $this->resolveMacro('crontab');
 		if (file_exists($crontab_file)) {
-			print "Deploying scheduled jobs from $crontab_file...\n";
+			$this->_debugOutput( "Deploying scheduled jobs from $crontab_file...", self::DEBUG_GENERAL);
 			$instance = $this->resolveMacro('instance');
 			$crontab_entries = trim(file_get_contents($crontab_file));
 			exec('crontab -l 2>&1', $current_crontab, $ret);
@@ -340,7 +350,7 @@
 
 			if ($ret == 1 || (count($current_crontab) == 1 && preg_match('/^no crontab for/i', $current_crontab))) {
 				// No current crontab
-				print "\tDeploying new crontab\n";
+				$this->_debugOutput( "\tDeploying new crontab", self::DEBUG_GENERAL);
 				$current_crontab = '';
 				$new_crontab = $crontab_entries_new . "\n";
 			} else {
@@ -348,10 +358,10 @@
 				
 				$regex = "/# wadf-deployment-begin: $instance.+# wadf-deployment-end: $instance - DO NOT REMOVE THIS/ms";
 				if (preg_match($regex, $current_crontab)) {
-					print "\tFound $instance in existing crontab, replacing\n";
+					$this->_debugOutput( "\tFound $instance in existing crontab, replacing", self::DEBUG_GENERAL);
 					$new_crontab = preg_replace($regex, $crontab_entries_new, $current_crontab);
 				} else {
-					print "\tCould not find $instance in existing crontab\n";
+					$this->_debugOutput( "\tCould not find $instance in existing crontab", self::DEBUG_GENERAL);
 					$new_crontab = $current_crontab . "\n" . $crontab_entries_new . "\n";
 				}
 			}
@@ -395,7 +405,7 @@
 			fputs($fp, implode('', $file_contents));
 			fclose($fp);
 		} else {
-			print "WARNING: Could not update list of local hostnames in hosts file '$hosts_file'. Check permissions.\n";
+			$this->_debugOutput( "WARNING: Could not update list of local hostnames in hosts file '$hosts_file'. Check permissions.", self::DEBUG_WARNING);
 		}
 	}
 	
@@ -408,7 +418,7 @@
 		// deploy vhost config
 		$source_file = $dir.'/'.$this->resolveMacro('vhost_config_template');
 		$dest_file = $this->resolveMacro('vhost_config_path').'/'.$this->resolveMacro('instance').'.conf';
-		//print "Copying $source_file to $dest_file\n";
+		$this->_debugOutput( "Copying $source_file to $dest_file", self::DEBUG_VERBOSE);
 		
 		$config = file_get_contents($source_file);
 		
@@ -458,7 +468,7 @@
 			fputs($fp, $config);
 			fclose($fp);
 		} else {
-			print "Could not open vhost config destination file '$dest_file'\n";
+			$this->_debugOutput( "Could not open vhost config destination file '$dest_file'");
 		}
 	}
 	
@@ -466,7 +476,7 @@
 	{
 		$cmd = $this->resolveMacro('post_deploy_script');
 		if ($cmd != '@post_deploy_script@' && !empty($cmd)) {		
-			print "Running post-deploy script $cmd...\n";
+			$this->_debugOutput( "Running post-deploy script $cmd...", self::DEBUG_GENERAL);
 			passthru($cmd);
 		}
 	}
@@ -476,12 +486,12 @@
 		$files = $this->resolveMacro('post_deploy_cleanup_files');
 		if (!empty($files) && $files != '@post_deploy_cleanup_files@') {
 			$deploy_path = $this->resolveMacro('deploy_path');
-			print "Cleaning up special files...\n";
+			$this->_debugOutput( "Cleaning up special files...", self::DEBUG_INFORMATION);
 			foreach(explode(' ', $files) as $file) {
 				$file = trim($file);
 				chdir($deploy_path);
 				if (file_exists($file) && file_exists("$file.template")) {
-					print "  Removing $file\n";
+					$this->_debugOutput( "  Removing $file", self::DEBUG_INFORMATION);
 					unlink($file);
 				}
 			}
@@ -492,7 +502,7 @@
 	{
 		$restart_cmd = $this->resolveMacro('webserver_restart_cmd');
 		if ($restart_cmd != '@webserver_restart_cmd@' && !empty($restart_cmd)) {
-			print "Restarting webserver...\n";
+			$this->_debugOutput( "Restarting webserver...", self::DEBUG_GENERAL);
 			passthru($restart_cmd);
 		}
 	}
@@ -505,7 +515,7 @@
 	{
 		$directives_out = array();
 		if (file_exists($file)) {
-			print "Processing PHP config file $file...\n";
+			$this->_debugOutput( "Processing PHP config file $file...", self::DEBUG_GENERAL);
 			$php_ini_directives = file($file);
 			$directives_out = array();
 			foreach ($php_ini_directives as $directive) {
@@ -525,7 +535,7 @@
 						$directives_out[] = "php_admin_value $directive_name $directive_value";
 					}
 				} else {
-					print "WARNING: Could not parse PHP ini config line from $file:\n\t$directive\n";
+					$this->_debugOutput( "WARNING: Could not parse PHP ini config line from $file:\n\t$directive", self::DEBUG_GENERAL);
 				}
 			}
 		}
@@ -543,7 +553,7 @@
 			$php_ini = $this->resolveMacro('php_config_location');
 			$php_ini_source = $dir . '/' . $php_ini;
 			if (file_exists($php_ini_source)) {
-				print "Deploying PHP config file $php_ini...\n";
+				$this->_debugOutput( "Deploying PHP config file $php_ini...", self::DEBUG_GENERAL);
 				
 				$source = file_get_contents($php_ini_source);
 				$php_ini_local = $this->resolveMacro('php_config_location_extra');
@@ -551,11 +561,11 @@
 					$extras = file_get_contents($php_ini_local);
 					$source .= "\n; PHP directives processed from $php_ini_local\n" . $extras;
 				}
-				
+
 				file_put_contents($php_ini_dest, $source);
 			}
 		} else {
-			print "ERROR: Unknown PHP type '$php_type'\n";
+			$this->_debugOutput( "ERROR: Unknown PHP type '$php_type'", self::DEBUG_GENERAL);
 		}
 	}
 	
@@ -565,7 +575,7 @@
 	 * @param string $destdir         The destination to check a working copy out to
 	 * @param string $revtype         One of the Tools_WADF::VCREFTYPE_* constants
 	 * @param string $rev_translated  The "translated" revision which makes sense according to $revtype. For tags, this is the tag. For branches, the branch name. For trunk, pass NULL.
-	 * @param string $raw_rev         Raw changeset number. Not valid for tags. Defaults to HEAD.
+	 * @param string $raw_rev         Raw changeset number. Not valid for tags. Defaults to H, self::DEBUG_GENERALEAD.
 	 */
 	public function checkout ($destdir, $revtype, $rev_translated, $raw_rev=null)
 	{
@@ -612,11 +622,11 @@
 		}
 		
 		$cmd = "svn $options $svn_action $vc_base/$this->appref/$svn_path $destdir";
-		print "Running $cmd\n";
+		$this->_debugOutput( "Running $cmd", self::DEBUG_VERBOSE);
 		exec($cmd, $output, $ret);
-		print implode("\n",$output)."\n";
+		$this->_debugOutput( implode("\n",$output), self::DEBUG_GENERAL);
 		if ($ret != 0) {
-			print "Error checking out\n";
+			$this->_debugOutput( "Error checking out");
 			exit(5);
 		}
 		
@@ -679,7 +689,7 @@
 		}
 		
 		if (empty($info->url) || empty($info->rev_raw)) {
-			//print "Could not read VC info from $dir\n";
+			$this->_debugOutput( "Could not read VC info from $dir", self::DEBUG_VERBOSE);
 			return false;
 		}
 		
@@ -692,7 +702,7 @@
 			$info->rev_type = Tools_WADF::VCREFTYPE_BRANCH;
 			$info->rev_translated = $matches[1];
 		} else {
-			print "Could not work out VC rev type from URL ". $info->url ."\n";
+			$this->_debugOutput( "Could not work out VC rev type from URL ". $info->url, self::DEBUG_GENERAL);
 			$info->rev_type = Tools_WADF::VCREFTYPE_UNKNOWN;
 			$info->rev_translated = 'unknown';
 		}
@@ -751,7 +761,7 @@
 			switch ($matches[1]) {
 				case 'trunk':
 					if (isset($matches[2])) {
-						print "trunk does not take a parameter\n";
+						$this->_debugOutput( "trunk does not take a parameter", self::DEBUG_GENERAL);
 						exit(5);
 					}
 					break;
@@ -799,7 +809,7 @@
 			$php_dir = $this->resolveMacro('php_dir');
 			
 			if (!file_exists($pear_config_file)) {
-				$cmd = "pear -v -c $pear_config_file ".
+				$cmd = "pear ".$this->_getPEARVerbosity()." -c $pear_config_file ".
 					"-d php_dir=$php_dir ".
 					"-d data_dir=$pear_path/data ".
 					"-d ext_dir=$pear_path/ext ".
@@ -810,10 +820,14 @@
 					"-d temp_dir=$pear_path/temp ".
 					"-d bin_dir=$pear_path ".
 					"-s";
-				exec($cmd);
+				$this->_runPEAR($cmd);//exec($cmd);
 					
-				print "Installing PEAR Core into $pear_path (config file is $pear_config_file)...\n";
-				passthru("pear -c $pear_config_file install --onlyreqdeps pear.php.net/PEAR");
+				$this->_debugOutput( "Installing PEAR Core into $pear_path (config file is $pear_config_file)...", self::DEBUG_INFORMATION);
+				
+				$cmd = "pear ".$this->_getPEARVerbosity()." -c $pear_config_file install --onlyreqdeps pear.php.net/PEAR";
+				$this->_runPEAR($cmd);
+				$this->_runPEAR("channel-update pear", false, false);
+//				passthru("pear ".$this->_getPEARVerbosity()." -c $pear_config_file install --onlyreqdeps pear.php.net/PEAR");
 			}
 			
 			$base_channel = $this->resolveMacro('dep_pear_base_channel');
@@ -826,27 +840,28 @@
 					$channel = $base_channel;
 				}
 				if (empty($channel)) trigger_error("Channel empty", E_USER_ERROR);
-				print "Discovering channel $channel...\n";
+				$this->_debugOutput( "Discovering channel $channel...", self::DEBUG_INFORMATION);
 				
 				// FIXME check if channel is already discovered and skip next step if so
 				
 				// With PEAR 1.6.x+ the base_channel can include username and
 				// password in the format username:password@channel
-				$this->_runPEAR("channel-discover $base_channel");
+				$this->_runPEAR("channel-discover $base_channel", false, false);
+				$this->_runPEAR("channel-update $channel", false, false);
 				if ($username) {
-					print "Logged in as user $username\n";
+					$this->_debugOutput( "Logged in as user $username", self::DEBUG_INFORMATION);
 				}
 			}
 		} else {
-			exec($this->_getPEARCmd() . ' config-get bin_dir', $output);
+			$this->_runPEAR($this->_getPEARCmd() . ' config-get bin_dir', $output);
 			$pear_path = $output[0];
-			echo "Using existing PEAR installation in $pear_path\n";
+			$this->_debugOutput("Using existing PEAR installation in $pear_path", self::DEBUG_INFORMATION);
 		}
 		
 		$this->_installPEARBaseRoles();
 		$this->_configurePEARBaseRoles($pear_path, $dir, $standalone_pear);
 		
-		print "Processing package.xml and installing PEAR dependencies...\n";
+		$this->_debugOutput( "Processing package.xml and installing PEAR dependencies...", self::DEBUG_INFORMATION);
 		$application_dir = '';
 		if (!$standalone_pear) {
 			// Deploy to the same directory. Is !$standalone_pear really the
@@ -861,10 +876,18 @@
 		$this->_setPearMacros();
 		
 	}
-	
+
+	protected function _getPEARVerbosity(){
+		//We are not using the quite option insted striping the output
+		if ($this->_debug < self::DEBUG_VERBOSE) {
+			return ''; 
+		} else {//DEBUG_VERBOSE
+			return ' -v '; 
+		}
+	}
+
 	protected function _installPEARBaseRoles()
 	{
-	
 		$base_roles = $this->resolveMacro('dep_pear_base_roles');
 		
 		if (!empty($base_roles)) {
@@ -875,7 +898,7 @@
 			foreach ($roles as $package) {
 				exec("$pear list $package", $out, $ret);
 				if ($ret != 0) {
-					print "Installing base role package $package...\n";
+					$this->_debugOutput( "Installing base role package $package...", self::DEBUG_INFORMATION);
 					$this->_runPEAR("install --soft --onlyreqdeps $base_roles");
 				}
 			}
@@ -905,14 +928,14 @@
 			unset($ret);
 			exec("$pear config-get -c $base_channel $var", $out, $ret);
 			if (empty($out[0]) || $standalone_pear) {
-				print "Setting $var = $value\n";
+				$this->_debugOutput( "Setting $var = $value", self::DEBUG_INFORMATION);
 				if (!empty($base_channel)) {
-					$this->_runPEAR("config-set -c $base_channel $var \"$value\"");
+					$this->_runPEAR("config-set -c $base_channel $var \"$value\"\n", false);
 				} else {
-					$this->_runPEAR("config-set $var \"$value\"");
+					$this->_runPEAR("config-set $var \"$value\"\n", false);
 				}
 			} else {
-				print "Base role config variable $var is already set ($out[0]) - not changing\n"; 
+				$this->_debugOutput( "Base role config variable $var is already set ($out[0]) - not changing", self::DEBUG_INFORMATION);
 			}
 		}
 	}
@@ -935,29 +958,88 @@
 		return $channel;
 	}
 	
-	protected function _runPEAR($cmd)
+	protected function _runPEAR($cmd, $output=true, $fail_on_error=true)
 	{
 		$pear_stability = $this->resolveMacro('dep_pear_preferred_stability');
 		if ($pear_stability) {
 			$pear_stability = "-d preferred_state=$pear_stability";
 		}
+		if(preg_match('/^pear/',$cmd)) {
+			$runcmd = $cmd; 
+		}else {
+			$runcmd = $this->_getPEARCmd() . " $pear_stability " . $cmd;			
+		}
+		
+		$this->_debugOutput("Running: $runcmd", self::DEBUG_VERBOSE);
+
+		exec($runcmd, $exec_output, $ret);
+		
+		
+		if($this->_debug < self::DEBUG_GENERAL) {
+			$output = false;
+			$strip = "/install|upgrade|optional|^\.+done\:|Starting to download|downloading/i";
+		} elseif ($this->_debug < self::DEBUG_INFORMATION) {
+			$strip = "/optional|^\.+done\:|Starting to download|downloading/i";
+		} elseif ($this->_debug < self::DEBUG_VERBOSE) {
+			$strip = $strip = "/^\.+done\:|Starting to download|downloading/i";
+		} else {//DEBUG_VERBOSE
+			$strip = false;
+		}
+		if ($fail_on_error && $ret != 0) {
+			$output = true;
+			echo "\n###################[  Failed  ]####################\n";
+		}
+		
+		if ($output) {
+			$warnings = array();
+			$deprecated = array();
+			foreach($exec_output as $line) {
+				if (preg_match("/WARNING: (.*)/i",$line,$m)) {
+					if(preg_match("/deprecated/",$line)){
+						$deprecated[] = $m[1];
+					} else {
+						$warnings[] = $m[1];
+					}
+				} elseif (!$strip) {
+					echo $line."\n";
+				} elseif (!preg_match($strip, $line)) {
+					echo $line."\n";
+				}
+			}
+
+			if (count($deprecated)>0 && $this->_debug >= self::DEBUG_INFORMATION) {
+				echo "\n";
+				foreach($deprecated as $line) {
+					echo 'Deprecated: '.$line."\n";
+				}
+			}			
+
+			if (count($warnings)>0 && $this->_debug >= self::DEBUG_WARNING) {
+				echo "\n###################[ Warnings ]####################\n";
+				foreach($warnings as $line) {
+					echo 'WARNING: '.$line."\n";
+				}
+				echo "\n";
+			}
+		}
 		
-		$runcmd = $this->_getPEARCmd() . " $pear_stability " . $cmd;
-		if ($this->_debug) print "Running: $runcmd\n";
-		passthru($runcmd, $ret);
+		if($fail_on_error && $ret != 0) {
+			exit;
+		}
 		return $ret;
 	}
 	
 	protected function _getPEARCmd()
-	{
+	{	$verbossity = $this->_getPEARVerbosity();
 		$pear_path = $this->resolveMacro('dep_pear_deploy_path');
 		if (empty($pear_path)) {
-			exec('pear config-get bin_dir', $output, $ret);
+			
+			exec('pear '.$verbossity.' config-get bin_dir', $output, $ret);
 			$pear_path = $output[0];
-			$runcmd = "$pear_path/pear";
+			$runcmd = "$pear_path/pear $verbossity";
 		} else {
 			$pear_config_file = $this->resolveMacro('dep_pear_config_file');
-			$runcmd = "$pear_path/pear -c $pear_config_file";
+			$runcmd = "$pear_path/pear $verbossity -c $pear_config_file";
 		}
 		return $runcmd;
 	}
@@ -1010,7 +1092,7 @@
 		exec("$pearcmd config-get download_dir", $output, $ret);
 		if ($ret == 0) {
 			$download_dir = $output[0];
-			print "Cleaning up PEAR temporary download files from $download_dir...\n";
+			$this->_debugOutput( "Cleaning up PEAR temporary download files from $download_dir...", self::DEBUG_INFORMATION);
 			$this->_rmDir($download_dir);
 		}
 		
@@ -1023,7 +1105,7 @@
 				exec("$pearcmd config-get doc_dir", $output, $ret);
 				if ($ret == 0) {
 					$doc_dir = $output[0];
-					print "Cleaning up PEAR document directory $doc_dir...\n";
+					$this->_debugOutput( "Cleaning up PEAR document directory $doc_dir...", self::DEBUG_INFORMATION);
 					$this->_rmDir($doc_dir);
 				}
 			}
@@ -1095,10 +1177,10 @@
 		$macros = array();
 		$files = $this->_listTemplateFiles($dir);
 		foreach ($files as $file) {
-			if ($this->_debug) $this->_debugOutput("extracting macros from file '$file'");
+			$this->_debugOutput("extracting macros from file '$file'", self::DEBUG_VERBOSE);
 			$contents = file_get_contents($file);
 			$new_macros = $this->extractMacrosFromString($contents);
-			if ($this->_debug) $this->_debugOutput("macros in file '$file' = ".implode(',',$new_macros));
+			$this->_debugOutput("macros in file '$file' = ".implode(',',$new_macros), self::DEBUG_VERBOSE);
 			$macros = array_merge($macros,$new_macros);
 			
 			
@@ -1157,12 +1239,12 @@
 				// like a variable as the second parameter very much.
 				chmod($kickstart_script, 0750);
 			
-				print "\nRunning kickstart script $kickstart_script...\n";
+				$this->_debugOutput( "\nRunning kickstart script $kickstart_script...", self::DEBUG_GENERAL);
 			
 				// Run the script
 				passthru($kickstart_script);
 			} else {
-				print "\nKickstart script $kickstart_script does not exist; nothing to do.\n";
+				$this->_debugOutput( "\nKickstart script $kickstart_script does not exist; nothing to do.", self::DEBUG_GENERAL);
 			}
 		}
 	}
@@ -1229,12 +1311,12 @@
 	public function processLocalConfig()
 	{
 		$app_conf_file = $this->resolveMacro('local_config');
-		print "Looking for $app_conf_file...\n";
+		$this->_debugOutput( "Looking for $app_conf_file...", self::DEBUG_GENERAL);
 		if (file_exists($app_conf_file)) {
-			print "\tFound. Loading configs from $app_conf_file\n";
+			$this->_debugOutput( "\tFound. Loading configs from $app_conf_file", self::DEBUG_GENERAL);
 			$this->readConfigFile($app_conf_file);
 		} else {
-			print "\tNot found\n";
+			$this->_debugOutput( "\tNot found", self::DEBUG_GENERAL);
 		}
 	}
 	
@@ -1256,7 +1338,7 @@
 				$value = $this->resolveMacro($key);
 				// TODO: make %% into a const
 				if ($value == '%%') {
-					print "Please enter the value for the config option '$key': ";
+					print "Please enter the value for the config option '$key': \n";
 					$input = trim(fgets(STDIN));
 					$input_values[$key] = $input;
 					
@@ -1373,7 +1455,7 @@
 	{
 		$config = parse_ini_file($file, TRUE);
 		if (isset($config['globals'])) {
-			print "Setting global configuration options from file $file\n";
+			$this->_debugOutput("Setting global configuration options from file $file", self::DEBUG_INFORMATION);
 			$this->_appendMacroDefs($config['globals']);
 		}
 		// We need to do this to ensure "profile" is set.
@@ -1384,7 +1466,7 @@
 		$this->resolveAllMacros();
 		$profile = $this->resolveMacro('profile');
 		if ($profile == '@profile@') {
-			print "Cannot resolve global profile when processing $file\n";
+			$this->_debugOutput("Cannot resolve global profile when processing $file", self::DEBUG_GENERAL);
 			$profile = null;
 		}
 		
@@ -1393,12 +1475,12 @@
 		if ($profile == null) {
 			if (isset($config['globals']['profile'])) {
 				$profile = $config['globals']['profile'];
-				print "File $file: Using profile='$profile' from 'globals' section of config\n";//TODO
+				$this->_debugOutput("File $file: Using profile='$profile' from 'globals' section of config", self::DEBUG_INFORMATION);//TODO
 			} else {
-				print "File $file: ignoring as no global profile set\n";
+				$this->_debugOutput("File $file: ignoring as no global profile set", self::DEBUG_GENERAL);
 			}
 		} else {
-			print "File $file: using profile section '$profile'\n";
+			$this->_debugOutput("File $file: using profile section '$profile'", self::DEBUG_INFORMATION);
 		}
 		
 		if (isset($config[$profile])) {
@@ -1411,15 +1493,17 @@
 		return array_values($this->_macro_fallbacks);
 	}
 	
-	protected function _debugOutput($string)
+	protected function _debugOutput($string, $level=self::DEBUG_GENERAL)
 	{
-		print "$string\n";
+		if ($level < $this->_debug) {
+			echo rtrim($string)."\n";
+		}
 	}
 	
 	// $string is a string which may contain all sorts of stuff including macros
 	public function resolveString ($string, $macro_values_stack = null, $context=null) {
 		if ($macro_values_stack === null) {
-		if ($this->_debug > 1) $this->_debugOutput("using default stack to resolve string");
+			$this->_debugOutput("using default stack to resolve string", self::DEBUG_VERBOSE);
 			$macro_values_stack = &$this->_macro_values;
 		}
 		
@@ -1435,7 +1519,7 @@
 	// $context is an optional context for recording errors
 	protected function _resolveString($string, &$macro_values_stack, $context=null)
 	{
-		if ($this->_debug > 1) $this->_debugOutput("resolving string '$string'");
+		$this->_debugOutput("resolving string '$string'", self::DEBUG_VERBOSE);
 
 		// take a copy for debugging
 		$origstring = $string;
@@ -1444,7 +1528,7 @@
 		while ($string != $oldstring) {
 			$oldstring = $string;
 			$macros = $this->extractMacrosFromString($string);
-			if ($this->_debug > 1) $this->_debugOutput("macros in string '$string' = ".implode(',',$macros));
+			$this->_debugOutput("macros in string '$string' = ".implode(',',$macros), self::DEBUG_VERBOSE);
 			foreach ($macros as $macro) {
 				$macro_contents = $this->_resolveMacro($macro, $macro_values_stack);
 				if ("@$macro@" == $macro_contents) {
@@ -1456,7 +1540,7 @@
 				}
 			}
 		}
-		if ($this->_debug > 1) $this->_debugOutput("resolved string '$origstring' to '$string'");
+		$this->_debugOutput("resolved string '$origstring' to '$string'", self::DEBUG_VERBOSE);
 		return $string;
 	}
 	
@@ -1469,10 +1553,10 @@
 		}
 		
 		while ($changed) {
-			if ($this->_debug > 1) $this->_debugOutput("resolveAllMacros: iterating");
+			$this->_debugOutput("resolveAllMacros: iterating", self::DEBUG_VERBOSE);
 			$changed = false;
 			foreach ($this->_macro_values as $macro_name => $macro_value) {
-				if ($this->_debug > 1) $this->_debugOutput("resolveAllMacros: resolving macro '$macro->name' ('$macro->value')");
+				$this->_debugOutput("resolveAllMacros: resolving macro '$macro->name' ('$macro->value')", self::DEBUG_VERBOSE);
 				$this->_macro_values[$macro_name] = $this->resolveString($macro_value);
 			
 				// If macro value has changed, we will need to iterate again
@@ -1480,7 +1564,7 @@
 					$changed = true;
 				}
 			
-				if ($this->_debug > 1) $this->_debugOutput("resolveAllMacros: resolved $macro->name to '".$this->_macro_values[$macro->name]."'");
+				$this->_debugOutput("resolveAllMacros: resolved $macro->name to '".$this->_macro_values[$macro->name]."'", self::DEBUG_VERBOSE);
 			}
 		}
 		return $this->_macro_values;
@@ -1498,7 +1582,7 @@
 	}
 	
 	protected function _resolveMacro ($macro, &$macro_values_stack) {
-		if ($this->_debug > 1) $this->_debugOutput("resolve single macro '$macro'");
+		$this->_debugOutput("resolve single macro '$macro'", self::DEBUG_VERBOSE);
 	
 		// make a copy
 		$origmacro = $macro;
@@ -1512,16 +1596,16 @@
 		}
 		
 		if (isset($macro_values_stack[$macro])) {
-			if ($this->_debug) $this->_debugOutput("found macro '$macro'");
+			$this->_debugOutput("found macro '$macro'", self::DEBUG_VERBOSE);
 			$output = $macro_values_stack[$macro];
 		} else {
 			$fallback_match = false;
 			foreach ($this->_macro_fallbacks as $fallback_regex => $fallback_macro) {
 				if (!$fallback_match) {
-					if ($this->_debug) $this->_debugOutput("trying fallback '$fallback_regex'");
+					$this->_debugOutput("trying fallback '$fallback_regex'", self::DEBUG_VERBOSE);
 					if (preg_match("/^$fallback_regex\$/", $macro, $matches)) {
 						$enum_value = $matches[1];
-						if ($this->_debug) $this->_debugOutput("matched fallback '$fallback_regex' - numbered '$enum_value'");
+						$this->_debugOutput("matched fallback '$fallback_regex' - numbered '$enum_value'", self::DEBUG_VERBOSE);
 						if ($enum_value == 1) $enum_value = '';
 						
 						// Now fill in the special enumerated macro with the relevant number
@@ -1533,7 +1617,7 @@
 						
 						// Fork off a new macro values stack
 						
-						if ($this->_debug) $this->_debugOutput("Forking new macro values stack with $special_macro = $enum_value");
+						$this->_debugOutput("Forking new macro values stack with $special_macro = $enum_value", self::DEBUG_VERBOSE);
 						$macro_values_special = $macro_values_stack;
 						
 						$macro_values_special[$special_macro] = $enum_value;
@@ -1572,7 +1656,7 @@
 			}
 		}
 		
-		if ($this->_debug) $this->_debugOutput("resolved single macro '$origmacro' to '$output'");
+		$this->_debugOutput("resolved single macro '$origmacro' to '$output'", self::DEBUG_VERBOSE);
 		
 		$macro_values_stack[$macro] = $output_unprocessed;
 		return $output;
