/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package flex.tools.debugger.cli;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.PrintStream;
import java.io.StringReader;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.Set;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.Vector;

import flash.localization.LocalizationManager;
import flash.tools.debugger.Bootstrap;
import flash.tools.debugger.DebuggerLocalizer;
import flash.tools.debugger.Frame;
import flash.tools.debugger.InProgressException;
import flash.tools.debugger.Isolate;
import flash.tools.debugger.IsolateSession;
import flash.tools.debugger.Location;
import flash.tools.debugger.NoResponseException;
import flash.tools.debugger.NotConnectedException;
import flash.tools.debugger.NotSupportedException;
import flash.tools.debugger.NotSuspendedException;
import flash.tools.debugger.PlayerDebugException;
import flash.tools.debugger.Session;
import flash.tools.debugger.SessionManager;
import flash.tools.debugger.SourceFile;
import flash.tools.debugger.SourceLocator;
import flash.tools.debugger.SuspendReason;
import flash.tools.debugger.SuspendedException;
import flash.tools.debugger.SwfInfo;
import flash.tools.debugger.Value;
import flash.tools.debugger.Variable;
import flash.tools.debugger.VariableAttribute;
import flash.tools.debugger.VariableType;
import flash.tools.debugger.VersionException;
import flash.tools.debugger.Watch;
import flash.tools.debugger.WatchKind;
import flash.tools.debugger.concrete.DProtocol;
import flash.tools.debugger.events.BreakEvent;
import flash.tools.debugger.events.ConsoleErrorFault;
import flash.tools.debugger.events.DebugEvent;
import flash.tools.debugger.events.ExceptionFault;
import flash.tools.debugger.events.FaultEvent;
import flash.tools.debugger.events.FileListModifiedEvent;
import flash.tools.debugger.events.FunctionMetaDataAvailableEvent;
import flash.tools.debugger.events.IsolateCreateEvent;
import flash.tools.debugger.events.IsolateExitEvent;
import flash.tools.debugger.events.SwfLoadedEvent;
import flash.tools.debugger.events.SwfUnloadedEvent;
import flash.tools.debugger.events.TraceEvent;
import flash.tools.debugger.expression.ECMA;
import flash.tools.debugger.expression.NoSuchVariableException;
import flash.tools.debugger.expression.PlayerFaultException;
import flash.tools.debugger.expression.ValueExp;
import flash.util.FieldFormat;
import flash.util.Trace;
import flex.tools.debugger.cli.ExpressionCache.EvaluationResult;
import flex.tools.debugger.cli.FaultActions.FaultActionsBuilder;

/**
 * This is a front end command line interface to the Flash Debugger
 * Player.
 *<p>
 * This tool utilizes the Debugger Java API (DJAPI) for Flash 
 * Player that exists in flash.tools.debuggger.
 *<p> 
 * This tool is not completely compliant with the API, since
 * some commands expose implementation specific information for
 * debugging purposes.  Instances where this occurs are kept to a
 * minimum and are isolated in a special class called Extensions.  
 * If you wish to build a version that is completely API 
 * compatible.  Replace Extensions with ExtensionsDisabled in 
 * the static method calls at the end of this file. 
 */
public class DebugCLI implements Runnable, SourceLocator
{
	public static final String VERSION			= "82"; //$NON-NLS-1$

	public static final int CMD_UNKNOWN			= 0;
	public static final int CMD_QUIT			= 1;
	public static final int CMD_CONTINUE		= 2;
	public static final int CMD_STEP			= 3;
	public static final int CMD_NEXT			= 4;
	public static final int CMD_FINISH			= 5;
	public static final int CMD_BREAK			= 6;
	public static final int CMD_SET				= 7;
	public static final int CMD_LIST			= 8;
	public static final int CMD_PRINT			= 9;
	public static final int CMD_TUTORIAL		= 10;
	public static final int CMD_INFO			= 11;
	public static final int CMD_HOME			= 12;
	public static final int CMD_RUN				= 13;
	public static final int CMD_FILE			= 14;
	public static final int CMD_DELETE			= 15;
	public static final int CMD_SOURCE			= 16;
	public static final int CMD_COMMENT			= 17;
	public static final int CMD_CLEAR			= 18;
	public static final int CMD_HELP			= 19;
	public static final int CMD_SHOW			= 20;
	public static final int CMD_KILL			= 21;
	public static final int CMD_HANDLE			= 22;
	public static final int CMD_ENABLE			= 23;
	public static final int CMD_DISABLE			= 24;
	public static final int CMD_DISPLAY			= 25;
	public static final int CMD_UNDISPLAY		= 26;
 	public static final int CMD_COMMANDS		= 27;
    public static final int CMD_PWD             = 28;
    public static final int CMD_CF              = 29;
    public static final int CMD_CONDITION		= 30;
	public static final int CMD_AWATCH			= 31;
	public static final int CMD_WATCH			= 32;
	public static final int CMD_RWATCH			= 33;
	public static final int CMD_WHAT			= 34;
	public static final int CMD_DISASSEMBLE		= 35;
	public static final int CMD_HALT			= 36;
	public static final int CMD_MCTREE			= 37;
	public static final int CMD_VIEW_SWF		= 38;
	public static final int CMD_DOWN			= 39;
	public static final int CMD_UP				= 40;
	public static final int CMD_FRAME			= 41;
	public static final int CMD_DIRECTORY		= 42;
	public static final int CMD_CATCH			= 43;
	public static final int CMD_CONNECT			= 44;
	public static final int CMD_WORKER			= 45;

	/* info sub commands */
	public static final int INFO_UNKNOWN_CMD	= 100;
	public static final int INFO_ARGS_CMD		= 101;
	public static final int INFO_BREAK_CMD		= 102;
	public static final int INFO_FILES_CMD		= 103;
	public static final int INFO_HANDLE_CMD		= 104;
	public static final int INFO_FUNCTIONS_CMD	= 105;
	public static final int INFO_LOCALS_CMD		= 106;
	public static final int INFO_SCOPECHAIN_CMD	= 107;
	public static final int INFO_SOURCES_CMD	= 108;
	public static final int INFO_STACK_CMD		= 109;
	public static final int INFO_VARIABLES_CMD	= 110;
	public static final int INFO_DISPLAY_CMD	= 111;
    public static final int INFO_TARGETS_CMD    = 112;
    public static final int INFO_SWFS_CMD		= 113;
    public static final int INFO_WORKERS_CMD	= 114;

	/* show subcommands */
	public static final int SHOW_UNKNOWN_CMD	= 200;
	public static final int SHOW_NET_CMD		= 201;
	public static final int SHOW_FUNC_CMD		= 202;
	public static final int SHOW_URI_CMD		= 203;
	public static final int SHOW_PROPERTIES_CMD	= 204;
	public static final int SHOW_FILES_CMD		= 205;
	public static final int SHOW_BREAK_CMD		= 206;
	public static final int SHOW_VAR_CMD		= 207;
	public static final int SHOW_MEM_CMD		= 208;
	public static final int SHOW_LOC_CMD		= 209;
	public static final int SHOW_DIRS_CMD		= 210;

	/* misc subcommands */
	public static final int ENABLE_ONCE_CMD		= 301;

    // default metadata retry count 8 attempts per waitForMetadata() call * 5 calls
    public static final int METADATA_RETRIES    = 8*5;
    
    /* Enum for the state of the initial prompt shown when a swf is loaded */
    public static enum InitialPromptState { NEVER_SHOWN, SHOWN_ONCE, DONE }  

	Stack<LineNumberReader> m_readerStack = new Stack<LineNumberReader>();
	public PrintStream m_err;
	public PrintStream m_out;
	Session		m_session;
	String		m_launchURI;
	boolean		m_fullnameOption; // emacs mode
	String		m_cdPath;
	String		m_mruURI;
	String m_connectPort;
	public final static String m_newline = System.getProperty("line.separator"); //$NON-NLS-1$

	private final static LocalizationManager m_localizationManager = new LocalizationManager();
	private final static FaultActionsBuilder faultActionsBuilder = new FaultActionsBuilder(m_localizationManager);
	
	List<String>	m_sourceDirectories; // List of String
	int				m_sourceDirectoriesChangeCount;
	private File	m_flexHomeDirectory; // <application.home>/frameworks/projects/*/src always goes in m_sourceDirectories
	private boolean	m_initializedFlexHomeDirectory;

	// context information for our current session
	FileInfoCache	m_fileInfo;
	FaultActions	m_faultTable;
	Vector<Integer> m_breakIsolates;
	ExpressionCache m_exprCache;
	Vector<BreakAction>	        m_breakpoints;
	Vector<WatchAction>			m_watchpoints;
	Vector<CatchAction>			m_catchpoints;
	ArrayList<DisplayAction>	m_displays;
//	boolean			m_requestResume;
//	boolean			m_requestHalt;
//	boolean			m_stepResume;
	int m_activeIsolate;
	DebugCLIIsolateState m_mainState;
	
	/* This indicates the isolate for which we have been showing prompts for setting 
	 * breakpoints( so that we don't switch worker while the user is setting breakpoints) */
	int m_lastPromptIsolate;
	
	private HashMap<Integer, DebugCLIIsolateState> m_isolateState;
	
	class DebugCLIIsolateState
	{
//		public FileInfoCache	m_fileInfo;
//		public ExpressionCache m_exprCache;
		public boolean			m_requestResume;
		public boolean			m_requestHalt;
		public boolean			m_stepResume;
		/* Indicates whether the prompt for setting initial breakpoints has been displayed for this isolate */
		public InitialPromptState			m_promptState;
//		public Vector<BreakAction>	        m_breakpoints;
//		public Vector<WatchAction>			m_watchpoints;
//		public Vector<CatchAction>			m_catchpoints;
//		public ArrayList<DisplayAction>	m_displays;

		
		public DebugCLIIsolateState(DebugCLI debugcli) {
//			m_exprCache = new ExpressionCache(debugcli);
			m_faultTable = faultActionsBuilder.build();//new FaultActions();
//			m_breakpoints = new Vector<BreakAction>();
//			m_watchpoints = new Vector<WatchAction>();
//			m_catchpoints = new Vector<CatchAction>();
//			m_displays = new ArrayList<DisplayAction>();
		}
	}
	
	private DebugCLIIsolateState getIsolateState(int isolateId) {
		if (isolateId == Isolate.DEFAULT_ID)
			return m_mainState;
		DebugCLIIsolateState isolateState = null;
		if (!m_isolateState.containsKey(isolateId)) {
			isolateState = new DebugCLIIsolateState(this);
			m_isolateState.put(isolateId, isolateState);
		}
		else
			isolateState = m_isolateState.get(isolateId);
		return isolateState;
	}
	
	public int getActiveIsolateId() {
		return m_activeIsolate;
	}
	
	private boolean getRequestResume(int isolateId) {
		return getIsolateState(isolateId).m_requestResume;
	}
	
	private void setRequestResume(boolean value, int isolateId) {
		getIsolateState(isolateId).m_requestResume = value;
	}
	
	private boolean getStepResume(int isolateId) {
		return getIsolateState(isolateId).m_stepResume;
	}
	
	private void setStepResume(boolean value, int isolateId) {
		getIsolateState(isolateId).m_stepResume = value;
	}
	
	private boolean getRequestHalt(int isolateId) {
		return getIsolateState(isolateId).m_requestHalt;
	}
	
	private void setRequestHalt(boolean value, int isolateId) {
		getIsolateState(isolateId).m_requestHalt = value;
	}
	
	private InitialPromptState getPromptState(int isolateId) {
		return getIsolateState(isolateId).m_promptState;
	}
	
	private void setPromptState(InitialPromptState value, int isolateId) {
		getIsolateState(isolateId).m_promptState = value;
	}

	/* our current input processing context */
	LineNumberReader	m_in;
	public LineNumberReader	m_keyboardStream;
	Vector<String>		m_keyboardInput;
	boolean				m_keyboardReadRequest;
	StringTokenizer		m_currentTokenizer;
	String				m_currentToken;
	String				m_currentLine;
	public String		m_repeatLine;	

	/**
	 * The module that the next "list" command should display if no
	 * module is explicitly specified.
	 */
	public static final String LIST_MODULE = "$listmodule"; //$NON-NLS-1$

	/**
	 * The line number at which the next "list" command should begin if no
	 * line number is explicitly specified.
	 */
	public static final String LIST_LINE = "$listline"; //$NON-NLS-1$
	
	public static final String LIST_WORKER = "$listworker"; //$NON-NLS-1$

	/**
	 * The number of lines displayed by the "list" command.
	 */
	private static final String LIST_SIZE = "$listsize"; //$NON-NLS-1$

	private static final String COLUMN_WIDTH = "$columnwidth"; //$NON-NLS-1$

	private static final String UPDATE_DELAY = "$updatedelay"; //$NON-NLS-1$

	private static final String HALT_TIMEOUT = "$halttimeout"; //$NON-NLS-1$

	/**
	 * Current breakpoint number.
	 */
	private static final String BPNUM = "$bpnum"; //$NON-NLS-1$

	/**
	 * Used to determine how much context information should be displayed.
	 */
	private static final String LAST_FRAME_DEPTH = "$lastframedepth"; //$NON-NLS-1$

	/**
	 * Used to determine how much context information should be displayed.
	 */
	private static final String CURRENT_FRAME_DEPTH = "$currentframedepth"; //$NON-NLS-1$

	/**
	 * The current frame we are viewing -- controlled by the "up", "down", and "frame" commands.
	 */
	public static final String DISPLAY_FRAME_NUMBER = "$displayframenumber"; //$NON-NLS-1$

	private static final String FILE_LIST_WRAP = "$filelistwrap"; //$NON-NLS-1$

	private static final String NO_WAITING = "$nowaiting"; //$NON-NLS-1$

	/**
	 * Show this pointer for info stack.
	 */
	private static final String INFO_STACK_SHOW_THIS = "$infostackshowthis"; //$NON-NLS-1$

	/**
	 * Number of milliseconds to wait for metadata.
	 */
	private static final String METADATA_ATTEMPTS_PERIOD = "$metadataattemptsperiod"; //$NON-NLS-1$

	private static final String METADATA_NOT_AVAILABLE = "$metadatanotavailable"; //$NON-NLS-1$

	/**
	 * How many times we should try to get metadata.
	 */
	private static final String METADATA_ATTEMPTS = "$metadataattempts"; //$NON-NLS-1$

	private static final String PLAYER_FULL_SUPPORT = "$playerfullsupport"; //$NON-NLS-1$

	/**
	 * Whether the "print" command will display attributes of members.
	 */
	public static final String DISPLAY_ATTRIBUTES = "$displayattributes"; //$NON-NLS-1$
	
	/* class's static init */
	static
	{
        // set up for localizing messages
        m_localizationManager.addLocalizer( new DebuggerLocalizer("flex.tools.debugger.cli.fdb.") ); //$NON-NLS-1$
	}

	public static void main(String[] args)
	{
		DebugCLI cli = new DebugCLI();

		/* attach our 'main' input method and out/err*/
		cli.m_err = System.err;
		cli.m_out = System.out;

		// get the default <application.home>/projects/frameworks/*/src entries into the source path
		cli.initSourceDirectoriesList();

		// a big of wrangling for our keyboard input stream since its special
		cli.m_keyboardStream = new LineNumberReader(new InputStreamReader(System.in));
		cli.pushStream(cli.m_keyboardStream);

		/* iterate through the args list */
		cli.processArgs(args);

		/* figure out $HOME and the current directory */
		String userHome = System.getProperty("user.home"); //$NON-NLS-1$
		String userDir = System.getProperty("user.dir"); //$NON-NLS-1$

		/*
		 * If the current directory is not $HOME, and a .fdbinit file exists in the current directory,
		 * then push it onto the stack of files to read.
		 * 
		 * Note, we want ./.fdbinit to be read AFTER $HOME/.fdbinit, but we push them in reverse
		 * order, because they're going onto a stack.  If we push them in reverse order, then they
		 * will be read in the correct order (last one pushed is the first one read).
		 */
		if (userDir != null && !userDir.equals(userHome))
		{
			try
			{
				FileReader sr = new FileReader(new File(userDir, ".fdbinit")); //$NON-NLS-1$
				cli.pushStream( new LineNumberReader(sr) );
			}
			catch(FileNotFoundException fnf) {}
		}

		/*
		 * If a .fdbinit file exists in the $HOME directory, then push it onto the stack of files
		 * to read.
		 * 
		 * Note, we want ./.fdbinit to be read AFTER $HOME/.fdbinit, but we push them in reverse
		 * order, because they're going onto a stack.  If we push them in reverse order, then they
		 * will be read in the correct order (last one pushed is the first one read).
		 */
		if (userHome != null)
		{
			try
			{
				FileReader sr = new FileReader(new File(userHome, ".fdbinit")); //$NON-NLS-1$
				cli.pushStream( new LineNumberReader(sr) );
			}
			catch(FileNotFoundException fnf) {}
		}

		cli.execute();
	}

	public DebugCLI()
	{
		m_fullnameOption = false;
		m_faultTable = faultActionsBuilder.build();
		m_exprCache = new ExpressionCache(this);
		m_breakpoints = new Vector<BreakAction>();
		m_watchpoints = new Vector<WatchAction>();
		m_catchpoints = new Vector<CatchAction>();
		m_displays = new ArrayList<DisplayAction>();
		m_keyboardInput = new Vector<String>();
		m_mruURI = null;
		m_sourceDirectories = new LinkedList<String>();
		
		initProperties();
		m_mainState = new DebugCLIIsolateState(this);
		m_lastPromptIsolate = -1;
		initIsolateState();
	}

	public static LocalizationManager getLocalizationManager() { return m_localizationManager; }
	public Session				getSession()	{ return m_session; }
	
	public FileInfoCache getFileCache()	{ 
			return m_fileInfo;
	}

	/**
	 * Convert a module to class name.  This is used
	 * by the ExpressionCache to find variables
	 * that live at royale package scope.   That
	 * is variables such as mx.core.Component.
	 */
	public String module2ClassName(int moduleId)
	{
		String pkg = null;
		try
		{
			SourceFile file = m_fileInfo.getFile(moduleId);
			pkg = file.getPackageName();
		}
		catch(Exception npe)
		{
			// didn't work ignore it.
		}
		return pkg;
	}

	LineNumberReader	popStream()						{ return m_readerStack.pop(); }
	public void				pushStream(LineNumberReader r)  { m_readerStack.push(r); }
	boolean				haveStreams()					{ return !m_readerStack.empty(); }

	public void processArgs(String[] args)
	{
		for(int i=0; i<args.length; i++)
		{
			String arg = args[i];
//			System.out.println("arg["+i+"]= '"+arg+"'");
			if (arg.charAt(0) == '-')
			{
				// its an option
				if (arg.equals("-unit")) // unit-testing mode //$NON-NLS-1$
				{
					System.setProperty("fdbunit", ""); //$NON-NLS-1$ //$NON-NLS-2$
				}
				else if (arg.equals("-fullname") || arg.equals("-f")) //$NON-NLS-1$ //$NON-NLS-2$
				{
					m_fullnameOption = true; // emacs mode
				}
				else if (arg.equals("-cd")) //$NON-NLS-1$
				{
					// consume the path
					if (i+1 < args.length)
						m_cdPath = args[i++];
				}
				else if (arg.equals("-p")) //$NON-NLS-1$
				{
					// consume the port
					if (i+1 < args.length)
						m_connectPort = args[++i];
				}
				else
				{
					err("Unknown command-line argument: " + arg); //$NON-NLS-1$
				}
			}
			else
			{
				// its a URI to run
				StringReader sr = new StringReader("run "+arg+m_newline); //$NON-NLS-1$
				pushStream( new LineNumberReader(sr) );
			}
		}
	}

	/**
	 * Dispose of the current line and read the next from the current stream, if its an empty
	 * line and we are console then repeat last line.
	 */
	protected String readLine() throws IOException
	{
		String line = null;
		if (haveStreams())
			line = m_in.readLine();
		else
			line = keyboardReadLine();

		setCurrentLine(line);
		return line;
	}

	/**
	 * The reader portion of our keyboard input routine
	 * Block until input arrives.
	 */
	synchronized String keyboardReadLine()
	{
		// enable a request then block on the queue
		m_keyboardReadRequest = true;
		try { wait(); } catch(InterruptedException ie) {}

		// pull from the front of the queue
		return m_keyboardInput.remove(0);
	}

	/**
	 * A seperate thread collects our input so that we can
	 * block in the doContinue on the main thread and then
	 * allow the user to interrupt us via keyboard input
	 * on this thread.
	 *
	 * We built the stupid thing in this manner, since readLine()
	 * will block no matter what and if we 'quit' we can't
	 * seem to kill this thread.  .close() doesn't work
	 * and Thread.stop(), etc. all fail to do the job.
	 *
	 * Thus we needed to take a request response approach
	 * so that we only block when requested to do so.
	 */
	public void run()
	{
		// while we have this stream
		while(m_keyboardStream != null)
		{
			try
			{
				// only if someone is requesting us to read do we do so...
				if (m_keyboardReadRequest)
				{
					// block on keyboard input and put it onto the end of the queue
					String s = m_keyboardStream.readLine();
					m_keyboardInput.add(s);

					// fullfilled request, now notify blocking thread.
					m_keyboardReadRequest = false;
					synchronized(this) { notifyAll(); }
				}
				else
					try { Thread.sleep(50); } catch(InterruptedException ie) {}
			}
			catch(IOException io)
			{
//				io.printStackTrace();
			}
		}
	}

	public void setCurrentLine(String s)
	{
		m_currentLine = s;
		if (m_currentLine == null)
			m_currentTokenizer = null;   /* eof */
		else
		{
			m_currentLine = m_currentLine.trim();

			/* if nothing provided on this command then pull our 'repeat' command  */
			if (m_repeatLine != null && !haveStreams() && m_currentLine.length() == 0)
				m_currentLine = m_repeatLine;

			m_currentTokenizer = new StringTokenizer(m_currentLine, " \n\r\t"); //$NON-NLS-1$
		}
	}

	/* Helpers for extracting tokens from the current line */
	public boolean		hasMoreTokens()									{ return m_currentTokenizer.hasMoreTokens(); }
	public String		nextToken()										{ m_currentToken = m_currentTokenizer.nextToken(); return m_currentToken; }
	public int			nextIntToken() throws NumberFormatException		{ nextToken(); return Integer.parseInt(m_currentToken);	}
	public long			nextLongToken() throws NumberFormatException	{ nextToken(); return Long.parseLong(m_currentToken);	}
	public String		restOfLine()									{ return m_currentTokenizer.nextToken("").trim(); } //$NON-NLS-1$

	public void execute()
	{
		/* dump console message */
		displayStartMessage();
		
		/* now fire our keyboard input thread */
		Thread t = new Thread(this, "Keyboard input"); //$NON-NLS-1$
		t.start();

		/* keep processing streams until we have no more to do */
		while(haveStreams())
		{
			try
			{
				m_in = popStream();
				process();
			}
			catch(EOFException eof)
			{
				; /* quite allright */
			}
			catch(IOException io)
			{
				Map<String, Object> args = new HashMap<String, Object>();
				args.put("exceptionMessage", io); //$NON-NLS-1$
				err(getLocalizationManager().getLocalizedTextString("errorWhileProcessingFile", args)); //$NON-NLS-1$
			}
		}

		/* we done kill everything */
		exitSession();

		// clear this thing, which also halts our other thread.
		m_keyboardStream = null;
	}

	public PrintStream getOut() { return m_out; }

	private void displayStartMessage()
	{
        String build = getLocalizationManager().getLocalizedTextString("defaultBuildName"); //$NON-NLS-1$

        try
        {
            Properties p = new Properties();
            p.load(this.getClass().getResourceAsStream("version.properties")); //$NON-NLS-1$
            String buildString = p.getProperty("build"); //$NON-NLS-1$
            if ((buildString != null) && (! buildString.equals(""))) //$NON-NLS-1$
            {
                build = buildString;
            }
        }
        catch (Throwable t)
        {
            // ignore
        }

        Map<String, Object> aboutMap = new HashMap<String, Object>(); aboutMap.put("build", build); //$NON-NLS-1$
        out(getLocalizationManager().getLocalizedTextString("about", aboutMap)); //$NON-NLS-1$
		out(getLocalizationManager().getLocalizedTextString("copyright")); //$NON-NLS-1$
	}

	void displayPrompt()
	{
		m_out.print("(fdb) "); //$NON-NLS-1$
	}

	void displayCommandPrompt()
	{
		m_out.print(">"); //$NON-NLS-1$
	}

	// add the given character n times to sb
	void repeat(StringBuilder sb, char c, int n)
	{
		while(n-- > 0)
			sb.append(c);
	}

	// Prompt the user to respond to a yes or no type question
	boolean yesNoQuery(String prompt) throws IOException
	{
		boolean result = false;
		m_out.print(prompt);
		m_out.print(getLocalizationManager().getLocalizedTextString("yesOrNoAppendedToAllQuestions")); //$NON-NLS-1$

		String in = readLine();
		if (in != null && in.equals(getLocalizationManager().getLocalizedTextString("singleCharacterUserTypesForYes"))) //$NON-NLS-1$
			result = true;
		else if (in != null && in.equals("escape")) //$NON-NLS-1$
			throw new IllegalArgumentException("escape"); //$NON-NLS-1$
		else
			out(getLocalizationManager().getLocalizedTextString("yesNoQueryNotConfirmed")); //$NON-NLS-1$
		return result;
	}

	public void err(String s)
	{
		// Doesn't make sense to send messages to stderr, because this is
		// an interactive application; and besides that, sending a combination
		// of interwoven but related messages to both stdout and stderr causes
		// the output to be in the wrong order sometimes.
		out(s);
	}

	public void out(String s)
	{
		if (s.length() > 0 && (s.charAt(s.length()-1) == '\n') )
			m_out.print(s);
		else
			m_out.println(s);
	}

	static String uft()
	{
		Runtime rt = Runtime.getRuntime();
		long free = rt.freeMemory(), total = rt.totalMemory(), used =  total - free;
//		long max = rt.maxMemory();
		java.text.NumberFormat nf = java.text.NumberFormat.getInstance() ;
//        System.out.println("used: "+nf.format(used)+" free: "+nf.format(free)+" total: "+nf.format(total)+" max: "+nf.format(max));
        return "Used "+nf.format(used)+" - free "+nf.format(free)+" - total "+nf.format(total); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
    }

	/**
	 * Add all properties that we know about
	 */
	void initProperties()
	{
		propertyPut(LIST_SIZE, 10);
		propertyPut(LIST_LINE, 1);
		propertyPut(LIST_MODULE, 1);  // default to module #1
		propertyPut(LIST_WORKER, Isolate.DEFAULT_ID);
		propertyPut(COLUMN_WIDTH, 70);
		propertyPut(UPDATE_DELAY, 25);
		propertyPut(HALT_TIMEOUT, 7000);
		propertyPut(BPNUM, 0);				// set current breakpoint number as something bad
		propertyPut(LAST_FRAME_DEPTH, 0);		// used to determine how much context information should be displayed
		propertyPut(CURRENT_FRAME_DEPTH, 0);   // used to determine how much context information should be displayed
		propertyPut(DISPLAY_FRAME_NUMBER, 0);  // houses the current frame we are viewing
		propertyPut(FILE_LIST_WRAP, 999999);   // default 1 file name per line
		propertyPut(NO_WAITING, 0);
		propertyPut(INFO_STACK_SHOW_THIS, 1); // show this pointer for info stack
	}

	// getter/setter for properties; in the expression cache, so that they can be used in expressions!
	public void propertyPut(String k, int v)  { m_exprCache.put(k,v); }
	public int  propertyGet(String k)		  { return ((Integer)m_exprCache.get(k)).intValue(); }
	public Set<String>  propertyKeys()		  { return m_exprCache.keySet(); }

	/**
	 * Process this reader until its done
	 */
	void process() throws IOException
	{
		boolean done = false;
		while(!done)
		{
			try
			{
				/**
				 * Now if we are in a session and that session is suspended then we go
				 * into a state where we wait for some user interaction to get us out
				 */
				runningLoop();

				/* if we are in the stdin then put out a prompt */
				if (!haveStreams())
					displayPrompt();

				/* now read in the next line */
				readLine();
				if (m_currentLine == null)
					break;

				done = processLine();
			}
			catch(NoResponseException nre)
			{
				err(getLocalizationManager().getLocalizedTextString("noResponseException")); //$NON-NLS-1$
			}
			catch(NotSuspendedException nse)
			{
				err(getLocalizationManager().getLocalizedTextString("notSuspendedException")); //$NON-NLS-1$
			}
			catch(AmbiguousException ae)
			{
				// we already put up a warning for the user
			}
			catch(IllegalStateException ise)
			{
				err(getLocalizationManager().getLocalizedTextString("illegalStateException")); //$NON-NLS-1$
			}
			catch(IllegalMonitorStateException ime)
			{
				err(getLocalizationManager().getLocalizedTextString("illegalMonitorStateException")); //$NON-NLS-1$
			}
			catch(NoSuchElementException nse)
			{
				err(getLocalizationManager().getLocalizedTextString("noSuchElementException")); //$NON-NLS-1$
			}
			catch(NumberFormatException nfe)
			{
				err(getLocalizationManager().getLocalizedTextString("numberFormatException")); //$NON-NLS-1$
			}
			catch(SocketException se)
			{
				Map<String, Object> socketArgs = new HashMap<String, Object>();
				socketArgs.put("message", se.getMessage()); //$NON-NLS-1$
				err(getLocalizationManager().getLocalizedTextString("socketException", socketArgs)); //$NON-NLS-1$
			}
			catch(VersionException ve)
			{
				err(getLocalizationManager().getLocalizedTextString("versionException")); //$NON-NLS-1$
			}
			catch(NotConnectedException nce)
			{
				// handled by isConnectionLost()
			}
			catch(Exception e)
			{
				err(getLocalizationManager().getLocalizedTextString("unexpectedError")); //$NON-NLS-1$
				err(getLocalizationManager().getLocalizedTextString("stackTraceFollows")); //$NON-NLS-1$
				e.printStackTrace();
			}

			// check for a lost connection and if it is clean-up!
			if (isConnectionLost())
			{
				try
				{
					dumpHaltState(false);
				}
				catch(PlayerDebugException pde)
				{
					err(getLocalizationManager().getLocalizedTextString("sessionEndedAbruptly")); //$NON-NLS-1$
				}
			}
		}
	}

	// check if we have lost the connect without our help...
	boolean isConnectionLost()
	{
		boolean lost = false;

		if (m_session != null && !m_session.isConnected())
			lost = true;

		return lost;
	}

	boolean haveConnection()
	{
		boolean have = false;

		if (m_session != null && m_session.isConnected())
			have = true;

		return have;
	}

	void doShow() throws AmbiguousException, PlayerDebugException
	{
		/* show without any args brings up help */
		if (!hasMoreTokens())
			out( getHelpTopic("show") ); //$NON-NLS-1$
		else
		{
			/* otherwise we have a boatload of options */
			String subCmdString = nextToken();
			int subCmd = showCommandFor(subCmdString);
			switch(subCmd)
			{
				case SHOW_NET_CMD:
					doShowStats();
					break;

				case SHOW_FUNC_CMD:
					doShowFuncs();
					break;

				case SHOW_URI_CMD:
					doShowUri();
					break;

				case SHOW_PROPERTIES_CMD:
					doShowProperties();
					break;

				case SHOW_FILES_CMD:
					doShowFiles();
					break;

				case SHOW_BREAK_CMD:
					doShowBreak();
					break;

				case SHOW_VAR_CMD:
					doShowVariable();
					break;

				case SHOW_MEM_CMD:
					doShowMemory();
					break;

				case SHOW_LOC_CMD:
					doShowLocations();
					break;

				case SHOW_DIRS_CMD:
					doShowDirectories();
					break;

				default:
					doUnknown("show", subCmdString); //$NON-NLS-1$
					break;
			}
		}
	}

	void doShowUri()
	{
		// dump the URI that the player has sent us
		try
		{
			StringBuilder sb = new StringBuilder();
			sb.append("URI = "); //$NON-NLS-1$
			sb.append( m_session.getURI() );
			out( sb.toString() );
		}
		catch(Exception e)
		{
			err(getLocalizationManager().getLocalizedTextString("noUriReceived")); //$NON-NLS-1$
		}
	}

	/**
	 * Dump the content of files in a raw format
	 */
	void doShowFiles()
	{
		try
		{
			StringBuilder sb = new StringBuilder();
			for (Isolate isolate : m_session.getWorkers()) {
			
				Iterator itr = m_fileInfo.getAllFiles(isolate.getId());

				while(itr.hasNext())
				{
					SourceFile m = (SourceFile) ((Map.Entry)itr.next()).getValue();

					String name = m.getName();
					int id = m.getId();
					String path = m.getFullPath();

					sb.append(id);
					sb.append(' ');
					sb.append(path);
					sb.append(", "); //$NON-NLS-1$
					sb.append(name);
					sb.append(" ("); //$NON-NLS-1$
					if (isolate.getId() == Isolate.DEFAULT_ID) {
						sb.append(getLocalizationManager().getLocalizedTextString("mainThread")); //$NON-NLS-1$
					}
					else {
						HashMap<String, Object> wArgs = new HashMap<String, Object>();
						wArgs.put("worker", isolate.getId() - 1); //$NON-NLS-1$
						sb.append(getLocalizationManager().getLocalizedTextString("inWorker", wArgs)); //$NON-NLS-1$
					}
					sb.append(")"); //$NON-NLS-1$
					sb.append(m_newline);
				}
			}
			out( sb.toString() );
		}
		catch(NullPointerException npe)
		{
			err(getLocalizationManager().getLocalizedTextString("noSourceFilesFound")); //$NON-NLS-1$
		}
	}

	void doShowMemory()
	{
		out(uft());
	}

	void doShowLocations()
	{
		StringBuilder sb = new StringBuilder();
		sb.append("Num Type           Disp Enb Address    What"+m_newline); //$NON-NLS-1$

		// our list of breakpoints
		int count = breakpointCount();
		for(int i=0; i<count; i++)
		{
			BreakAction b = breakpointAt(i);
			int num = b.getId();

			FieldFormat.formatLong(sb, num, 3);
			sb.append(" breakpoint     "); //$NON-NLS-1$

			if (b.isAutoDisable())
				sb.append("dis  "); //$NON-NLS-1$
			else if (b.isAutoDelete())
				sb.append("del  "); //$NON-NLS-1$
			else
				sb.append("keep "); //$NON-NLS-1$

			if (b.isEnabled())
				sb.append("y   "); //$NON-NLS-1$
			else
				sb.append("n   "); //$NON-NLS-1$

			Iterator<Location> itr = b.getLocations().iterator();
			while(itr.hasNext())
			{
				Location l = itr.next();
				SourceFile file = l.getFile();
				String funcName = (file == null)
						? getLocalizationManager().getLocalizedTextString("unknownBreakpointLocation") //$NON-NLS-1$
								: file.getFunctionNameForLine(m_session, l.getLine()) ;
						int offset = adjustOffsetForUnitTests((file == null) ? 0 : file.getOffsetForLine(l.getLine()));

						sb.append("0x"); //$NON-NLS-1$
						FieldFormat.formatLongToHex(sb, offset, 8);
						sb.append(' ');

						if (funcName != null)
						{
							Map<String, Object> funcArgs = new HashMap<String, Object>();
							funcArgs.put("functionName", funcName); //$NON-NLS-1$
							sb.append(getLocalizationManager().getLocalizedTextString("inFunctionAt", funcArgs)); //$NON-NLS-1$
						}

						sb.append(file.getName());
						if (file != null)
						{
							sb.append("#"); //$NON-NLS-1$
							sb.append(file.getId());
						}
						sb.append(':');
						sb.append(l.getLine());

						try
						{
							SwfInfo info = m_fileInfo.swfForFile(file, l.getIsolateId());
							Map<String, Object> swfArgs = new HashMap<String, Object>();
							swfArgs.put("swf", FileInfoCache.shortNameOfSwf(info)); //$NON-NLS-1$
							sb.append(getLocalizationManager().getLocalizedTextString("inSwf", swfArgs)); //$NON-NLS-1$
							if (l.getIsolateId() == Isolate.DEFAULT_ID) {
								sb.append(" ("); //$NON-NLS-1$
								sb.append(getLocalizationManager().getLocalizedTextString("mainThread")); //$NON-NLS-1$
								sb.append(")"); //$NON-NLS-1$
							}
							else {
								swfArgs = new HashMap<String, Object>();
								swfArgs.put("worker", l.getIsolateId() - 1); //$NON-NLS-1$
								sb.append(" ("); //$NON-NLS-1$
								sb.append(getLocalizationManager().getLocalizedTextString("inWorker", swfArgs)); //$NON-NLS-1$
								sb.append(")"); //$NON-NLS-1$
							}
						}
						catch(NullPointerException npe)
						{
							// can't find the swf
							sb.append(getLocalizationManager().getLocalizedTextString("nonRestorable")); //$NON-NLS-1$
						}
						sb.append(m_newline);
						if (itr.hasNext())
							sb.append("                            "); //$NON-NLS-1$
			}
		}
		out(sb.toString());
	}

	/**
	 * When running unit tests, we want byte offsets into the file to
	 * always be displayed as zero, so that the unit test expected
	 * results will match up with the actual results.  This is just a
	 * simple helper function that deals with that.
	 */
	private int adjustOffsetForUnitTests(int offset)
	{
		if (System.getProperty("fdbunit")==null) //$NON-NLS-1$
			return offset;
		else
			return 0;
	}

	void doShowDirectories()
	{
		out(getLocalizationManager().getLocalizedTextString("sourceDirectoriesSearched")); //$NON-NLS-1$
		Iterator<String> iter = m_sourceDirectories.iterator();
		while (iter.hasNext())
		{
			String dir = iter.next();
			out("  " + dir); //$NON-NLS-1$
		}
	}

	void doHalt() throws SuspendedException, NotConnectedException, NoResponseException
	{
		out(getLocalizationManager().getLocalizedTextString("attemptingToSuspend")); //$NON-NLS-1$
		IsolateSession session = m_session.getWorkerSession(getActiveIsolateId());
		if (!session.isSuspended())
			session.suspend();
		if (session.isSuspended())
			out(getLocalizationManager().getLocalizedTextString("playerStopped")); //$NON-NLS-1$
		else
			out(getLocalizationManager().getLocalizedTextString("playerRunning")); //$NON-NLS-1$
	}

	public void appendReason(StringBuilder sb, int reason)
	{
		switch(reason)
		{
			case SuspendReason.Unknown:
				sb.append(getLocalizationManager().getLocalizedTextString("suspendReason_Unknown")); //$NON-NLS-1$
				break;

			case SuspendReason.Breakpoint:
				sb.append(getLocalizationManager().getLocalizedTextString("suspendReason_HitBreakpoint")); //$NON-NLS-1$
				break;

			case SuspendReason.Watch:
				sb.append(getLocalizationManager().getLocalizedTextString("suspendReason_HitWatchpoint")); //$NON-NLS-1$
				break;

			case SuspendReason.Fault:
				sb.append(getLocalizationManager().getLocalizedTextString("suspendReason_ProgramThrewException")); //$NON-NLS-1$
				break;

			case SuspendReason.StopRequest:
				sb.append(getLocalizationManager().getLocalizedTextString("suspendReason_StopRequest")); //$NON-NLS-1$
				break;

			case SuspendReason.Step:
				sb.append(getLocalizationManager().getLocalizedTextString("suspendReason_ProgramFinishedStepping")); //$NON-NLS-1$
				break;

			case SuspendReason.HaltOpcode:
				sb.append(getLocalizationManager().getLocalizedTextString("suspendReason_HaltOpcode")); //$NON-NLS-1$
				break;

			case SuspendReason.ScriptLoaded:
				sb.append(getLocalizationManager().getLocalizedTextString("suspendReason_ScriptHasLoadedIntoFlashPlayer")); //$NON-NLS-1$
				break;
		}
	}

	/**
	 * The big ticket item, where all your questions are answered.
	 *
	 */
	void doInfo() throws AmbiguousException, PlayerDebugException
	{
		/* info without any args brings up help */
		if (!hasMoreTokens())
			out( getHelpTopic("info") ); //$NON-NLS-1$
		else
		{
			/* otherwise we have a boatload of options */
			String subCmdString = nextToken();
			int subCmd = infoCommandFor(subCmdString);
			switch(subCmd)
			{
				case INFO_ARGS_CMD:
					doInfoArgs();
					break;

				case INFO_BREAK_CMD:
					doInfoBreak();
					break;

				case INFO_FILES_CMD:
					doInfoFiles();
					break;

				case INFO_FUNCTIONS_CMD:
					doInfoFuncs();
					break;

				case INFO_HANDLE_CMD:
					doInfoHandle();
					break;

				case INFO_LOCALS_CMD:
					doInfoLocals();
					break;

				case INFO_SCOPECHAIN_CMD:
					doInfoScopeChain();
					break;
					
				case INFO_SOURCES_CMD:
					doInfoSources();
					break;

				case INFO_STACK_CMD:
					doInfoStack();
					break;

				case INFO_VARIABLES_CMD:
					doInfoVariables();
					break;

				case INFO_DISPLAY_CMD:
					doInfoDisplay();
					break;

                case INFO_TARGETS_CMD:
                    doInfoTargets();
                    break;

                case INFO_SWFS_CMD:
                    doInfoSwfs();
                    break;
                    
                case INFO_WORKERS_CMD:
                	doInfoWorkers();
                	break;

				default:
					doUnknown("info", subCmdString); //$NON-NLS-1$
					break;
			}
		}
	}
	
	void doInfoWorkers() throws NotConnectedException, NotSupportedException, NotSuspendedException, NoResponseException
	{
//		waitTilHalted();
		Isolate[] isolates = m_session.getWorkers();
		if (isolates == null || isolates.length == 0) {
			out(getLocalizationManager().getLocalizedTextString("noWorkersRunning")); //$NON-NLS-1$
			return;
		}
		StringBuilder sb = new StringBuilder();
		for (Isolate t : isolates) {
			String status = getLocalizationManager().getLocalizedTextString("workerRunning"); //$NON-NLS-1$
			if (m_session.getWorkerSession(t.getId()).isSuspended()) {
				status = getLocalizationManager().getLocalizedTextString("workerSuspended"); //$NON-NLS-1$
			}
			if (m_activeIsolate == t.getId()) {
				status += " " + getLocalizationManager().getLocalizedTextString("workerSelected"); //$NON-NLS-1$ //$NON-NLS-2$
			}
			if (t.getId() == Isolate.DEFAULT_ID) {
				sb.append(getLocalizationManager().getLocalizedTextString("mainThread")); //$NON-NLS-1$
				sb.append(" "); //$NON-NLS-1$
				sb.append(Isolate.DEFAULT_ID - 1);
			}
			else {
				HashMap<String, Object> workArgs = new HashMap<String, Object>();
				workArgs.put("worker", (t.getId() - 1)); //$NON-NLS-1$
				sb.append(getLocalizationManager().getLocalizedTextString("inWorker", workArgs)); //$NON-NLS-1$
			}
			sb.append(" - " + status + m_newline); //$NON-NLS-1$
		}
		out(sb.toString());
	}


	void doInfoStack() throws PlayerDebugException
	{
		waitTilHalted(m_activeIsolate);

		StringBuilder sb = new StringBuilder();
		Frame[] stack = m_session.getWorkerSession(m_activeIsolate).getFrames();
		if (stack == null || stack.length == 0)
			sb.append(getLocalizationManager().getLocalizedTextString("noStackAvailable")); //$NON-NLS-1$
		else
		{
			boolean showThis = propertyGet(INFO_STACK_SHOW_THIS) == 1;
			for(int i=0; i<stack.length; i++)
			{
				// keep spitting out frames until we can't
				Frame frame = stack[i];
				boolean valid = appendFrameInfo(sb, frame, i, showThis, false);
				sb.append(m_newline);
                if (!valid)
                    break;
			}
		}

		/* dump it out */
		out(sb.toString());
	}
	
	/**
	 * Spit out frame information for a given frame number 
	 */
	boolean appendFrameInfo(StringBuilder sb, Frame ctx, int frameNumber, boolean showThis, boolean showFileId) throws PlayerDebugException
	{
		boolean validFrame = true;

		// some formatting properties
		int i = frameNumber;

		Location loc = ctx.getLocation();
		SourceFile file = loc.getFile();
		int line = loc.getLine();
		String name = (file == null) ? "<null>" : file.getName(); //$NON-NLS-1$
		String sig = ctx.getCallSignature();
		String func = extractFunctionName(sig);

		// file == null or line < 0 appears to be a terminator for stack info
		if (file == null && line < 0)
        {
            validFrame = false;
        }
        else
		{
			Variable[] var = ctx.getArguments(m_session);
			Variable dis = ctx.getThis(m_session);
			boolean displayArgs = (func != null) || (var != null);

			sb.append('#');
			FieldFormat.formatLong(sb, i, 3);
			sb.append(' ');

			if (showThis && dis != null)
			{
				ExpressionCache.appendVariable(sb, dis, ctx.getIsolateId());
				sb.append("."); //$NON-NLS-1$
			}

			if (func != null)
				sb.append(func);

			if (displayArgs)
			{
				sb.append('(');
				for (int j=0; j<var.length; j++)
				{
					Variable v = var[j];
					sb.append(v.getName());
					sb.append('=');
					ExpressionCache.appendVariableValue(sb, v.getValue(), ctx.getIsolateId());
					if ((j+1)<var.length)
						sb.append(", "); //$NON-NLS-1$
				}
				sb.append(")"); //$NON-NLS-1$
				sb.append(getLocalizationManager().getLocalizedTextString("atFilename")); //$NON-NLS-1$
			}

			sb.append(name);

			// if this file is currently being filtered put the source file id after it
			if (file != null && (showFileId || !m_fileInfo.inFileList(file)))
			{
				sb.append('#');
				sb.append( file.getId() );

			}
			sb.append(':');
			sb.append(line);
		}
        return validFrame;
	}

	/** extract the function name from a signature */
	public static String extractFunctionName(String sig)
	{ 
		// strip everything after the leading ( 
		int at = sig.indexOf('(');
		if (at > -1)
			sig = sig.substring(0, at);

		// trim the leading [object_name::] since it doesn't seem to add much
		if (sig != null && (at = sig.indexOf("::")) > -1) //$NON-NLS-1$
			sig = sig.substring(at+2);

		return sig;
	}

	void doInfoVariables() throws PlayerDebugException
	{
		waitTilHalted(m_activeIsolate);

		// dump a set of locals
		StringBuilder sb = new StringBuilder();

		// use our expression cache formatting routine
		try
		{
			Variable[] vars = m_session.getWorkerSession(m_activeIsolate).getVariableList();
			for(int i=0; i<vars.length; i++)
			{
				Variable v = vars[i];

				// all non-local and non-arg variables
				if ( !v.isAttributeSet(VariableAttribute.IS_LOCAL) &&
					 !v.isAttributeSet(VariableAttribute.IS_ARGUMENT) )
				{
					ExpressionCache.appendVariable(sb, vars[i], m_activeIsolate);
					sb.append(m_newline);
				}
			}
		}
		catch(NullPointerException npe)
		{
			sb.append(getLocalizationManager().getLocalizedTextString("noVariables")); //$NON-NLS-1$
		}

		out(sb.toString());
	}

	void doInfoDisplay()
	{
		StringBuilder sb = new StringBuilder();
		sb.append("Num Enb Expression"+m_newline); //$NON-NLS-1$

		// our list of displays
		int count = displayCount();
		for(int i=0; i<count; i++)
		{
			DisplayAction b = displayAt(i);
			int num = b.getId();
			String exp = b.getContent();

			sb.append(':');
			FieldFormat.formatLong(sb, num, 3);

			if (b.isEnabled())
				sb.append(" y  "); //$NON-NLS-1$
			else
				sb.append(" n  "); //$NON-NLS-1$

			sb.append(exp);
			sb.append(m_newline);
		}

		out(sb.toString());
	}

	void doInfoArgs() throws PlayerDebugException
	{
		waitTilHalted(m_activeIsolate);

		// dump a set of locals
		StringBuilder sb = new StringBuilder();

		// use our expression cache formatting routine
		try
		{
			int num = propertyGet(DISPLAY_FRAME_NUMBER);
			Frame[] frames = m_session.getWorkerSession(m_activeIsolate).getFrames();
			Variable[] vars = frames[num].getArguments(m_session);
			for(int i=0; i<vars.length; i++)
			{
				ExpressionCache.appendVariable(sb, vars[i], m_activeIsolate);
				sb.append(m_newline);
			}
		}
		catch(NullPointerException npe)
		{
			sb.append(getLocalizationManager().getLocalizedTextString("noArguments")); //$NON-NLS-1$
		}
        catch(ArrayIndexOutOfBoundsException aix)
        {
            sb.append(getLocalizationManager().getLocalizedTextString("notInValidFrame")); //$NON-NLS-1$
        }

		out(sb.toString());
	}

	void doInfoLocals() throws PlayerDebugException
	{
		waitTilHalted(m_activeIsolate);

		// dump a set of locals
		StringBuilder sb = new StringBuilder();

		// use our expression cache formatting routine
		try
		{
			// get the variables from the requested frame
			int num = propertyGet(DISPLAY_FRAME_NUMBER);
			Frame[] ar = m_session.getWorkerSession(m_activeIsolate).getFrames();
			Frame ctx = ar[num];
			Variable[] vars = ctx.getLocals(m_session);

			for(int i=0; i<vars.length; i++)
			{
				Variable v = vars[i];

				// see if variable is local
				if ( v.isAttributeSet(VariableAttribute.IS_LOCAL) )
				{
					ExpressionCache.appendVariable(sb, v, m_activeIsolate);
					sb.append(m_newline);
				}
			}
		}
		catch(NullPointerException npe)
		{
			sb.append(getLocalizationManager().getLocalizedTextString("noLocals")); //$NON-NLS-1$
		}
        catch(ArrayIndexOutOfBoundsException aix)
        {
            sb.append(getLocalizationManager().getLocalizedTextString("notInValidFrame")); //$NON-NLS-1$
        }

		out(sb.toString());
	}

	void doInfoScopeChain() throws PlayerDebugException
	{
		waitTilHalted(m_activeIsolate);

		// dump the scope chain
		StringBuilder sb = new StringBuilder();

		// use our expression cache formatting routine
		try
		{
			// get the scope chainfrom the requested frame
			int num = propertyGet(DISPLAY_FRAME_NUMBER);
			Frame[] ar = m_session.getWorkerSession(m_activeIsolate).getFrames();
			Frame ctx = ar[num];
			Variable[] scopes = ctx.getScopeChain(m_session);

			for(int i=0; i<scopes.length; i++)
			{
				Variable scope = scopes[i];
				ExpressionCache.appendVariable(sb, scope, m_activeIsolate);
				sb.append(m_newline);
			}
		}
		catch(NullPointerException npe)
		{
			sb.append(getLocalizationManager().getLocalizedTextString("noScopeChain")); //$NON-NLS-1$
		}
        catch(ArrayIndexOutOfBoundsException aix)
        {
            sb.append(getLocalizationManager().getLocalizedTextString("notInValidFrame")); //$NON-NLS-1$
        }

		out(sb.toString());
	}
	
	void doInfoTargets()
    {
        if (!haveConnection())
		{
			out(getLocalizationManager().getLocalizedTextString("noActiveSession")); //$NON-NLS-1$
			if (m_launchURI != null)
			{
				Map<String, Object> args = new HashMap<String, Object>();
				args.put("uri", m_launchURI); //$NON-NLS-1$
				out(getLocalizationManager().getLocalizedTextString("runWillLaunchUri", args)); //$NON-NLS-1$
			}
		}
        else
		{
			String uri = m_session.getURI();
			if (uri == null || uri.length() < 1)
				err(getLocalizationManager().getLocalizedTextString("targetUnknown")); //$NON-NLS-1$
			else
				out(uri);
		}
    }

	/**
	 * Dump some stats about our currently loaded swfs.
	 */
    void doInfoSwfs()
    {
		try
		{
			StringBuilder sb = new StringBuilder();
			SwfInfo[] swfs = m_fileInfo.getSwfs(m_activeIsolate);
			for(int i=0; i<swfs.length; i++)
			{
				SwfInfo e = swfs[i];
				if (e == null || e.isUnloaded())
					continue;

				Map<String, Object> args = new HashMap<String, Object>();
				args.put("swfName", FileInfoCache.nameOfSwf(e)); //$NON-NLS-1$
				args.put("size", NumberFormat.getInstance().format(e.getSwfSize())); //$NON-NLS-1$

				try
				{
					int size = e.getSwdSize(m_session);

					// our swd is loaded so let's comb through our
					// list of scripts and locate the range of ids.
					SourceFile[] files = e.getSourceList(m_session);
					int max = Integer.MIN_VALUE;
					int min = Integer.MAX_VALUE;
					for(int j=0; j<files.length; j++)
					{
						SourceFile f = files[j];
						int id = f.getId();
						max = (id > max) ? id : max;
						min = (id < min) ? id : min;
					}

					args.put("scriptCount", Integer.toString(e.getSourceCount(m_session))); //$NON-NLS-1$
					args.put("min", Integer.toString(min)); //$NON-NLS-1$
					args.put("max", Integer.toString(max)); //$NON-NLS-1$
					args.put("plus", (e.isProcessingComplete()) ? "+" : ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
					args.put("moreInfo", (size==0) ? getLocalizationManager().getLocalizedTextString("remainingSourceBeingLoaded") : ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				}
				catch(InProgressException ipe)
				{
					sb.append(getLocalizationManager().getLocalizedTextString("debugInfoBeingLoaded")); //$NON-NLS-1$
				}
				args.put("url", e.getUrl()); //$NON-NLS-1$
				sb.append(getLocalizationManager().getLocalizedTextString("swfInfo", args)); //$NON-NLS-1$
				sb.append(m_newline);
			}
			out( sb.toString() );
		}
		catch(NullPointerException npe)
		{
			err(getLocalizationManager().getLocalizedTextString("noSWFs")); //$NON-NLS-1$
		}
    }

	private static final int AUTHORED_FILE = 1;		// a file that was created by the end user, e.g. MyApp.mxml
	private static final int FRAMEWORK_FILE = 2;	// a file from the Flex framework, e.g. mx.controls.Button.as, see FRAMEWORK_FILE_PACKAGES
	private static final int SYNTHETIC_FILE = 3;	// e.g. "<set up XML utilities.1>"
	private static final int ACTIONS_FILE = 4;		// e.g. "Actions for UIComponent: Frame 1 of Layer Name Layer 1"

    private static final String[] FRAMEWORK_FILE_PACKAGES // package prefixes that we consider FRAMEWORK_FILEs
        = new String[] {"mx","flex","text"}; // 'text' is Vellum (temporary) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

	/**
	 * Given a file, guesses what type it is -- e.g. a file created by the end user,
	 * or a file from the Flex framework, etc.
	 */
	private int getFileType(SourceFile sourceFile)
	{
		String name = sourceFile.getName();
		String pkg = sourceFile.getPackageName();

		if (name.startsWith("<") && name.endsWith(">") || name.equals("GeneratedLocale")) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			return SYNTHETIC_FILE;

        for (final String frameworkPkg : FRAMEWORK_FILE_PACKAGES )
        {
            // look for packages starting with pkgName
            if (pkg.startsWith(frameworkPkg + '\\') ||
                pkg.startsWith(frameworkPkg + '/')  ||
                pkg.equals(frameworkPkg))
            {
                return FRAMEWORK_FILE;
            }
        }

        if (name.startsWith("Actions for")) //$NON-NLS-1$
            return ACTIONS_FILE;

        return AUTHORED_FILE;
}

	void buildFileList(StringBuilder sb, boolean authoredFilesOnly)
	{
		SourceFile[] ar = m_fileInfo.getFileList(m_activeIsolate);
		if (ar == null)
		{
			err(getLocalizationManager().getLocalizedTextString("noSourceFilesFound")); //$NON-NLS-1$
			return;
		}

		Vector<String> authoredFiles = new Vector<String>();
		Vector<String> frameworkFiles = new Vector<String>();
		Vector<String> syntheticFiles = new Vector<String>();
		Vector<String> actionsFiles = new Vector<String>();

		for (int i = 0; i < ar.length; i++)
		{
 			SourceFile m = ar[i];
			int fileType = getFileType(m);
			int id = m.getId();
//			int fakeId = m_fileInfo.getFakeId(m);
			String entry = m.getName() + "#" + id; //$NON-NLS-1$

			switch (fileType)
			{
			case SYNTHETIC_FILE:
				syntheticFiles.add(entry);
				break;
			case FRAMEWORK_FILE:
				frameworkFiles.add(entry);
				break;
			case ACTIONS_FILE:
				actionsFiles.add(entry);
				break;
			case AUTHORED_FILE:
				authoredFiles.add(entry);
				break;
			}
		}

		int wrapAt = propertyGet(FILE_LIST_WRAP);

		if (!authoredFilesOnly)
		{
			if (actionsFiles.size() > 0)
			{
				appendStrings(sb, actionsFiles, (actionsFiles.size() > wrapAt) );
			}

			if (frameworkFiles.size() > 0)
			{
				sb.append("---"+m_newline); //$NON-NLS-1$
				appendStrings(sb, frameworkFiles, (frameworkFiles.size() > wrapAt) );
			}

			if (syntheticFiles.size() > 0)
			{
				sb.append("---"+m_newline); //$NON-NLS-1$
				appendStrings(sb, syntheticFiles, (syntheticFiles.size() > wrapAt) );
			}

			sb.append("---"+m_newline); //$NON-NLS-1$
		}

		appendStrings(sb, authoredFiles, (authoredFiles.size() > wrapAt) );
	}

	/**
	 * Dump a list of strings contained a vector
	 * If flow is set then the strings are placed
	 * on a single line and wrapped at $columnwidth
	 */
	void appendStrings(StringBuilder sb, Vector<String> v, boolean flow)
	{
		int count = v.size();
		int width = 0;
		int maxCol = propertyGet(COLUMN_WIDTH);

		for (int i = 0; i < count; i++)
		{
			String s = v.get(i);
			sb.append(s);

			// too many of them, then wrap according to columnwidth
			if (flow)
			{
				width += (s.length() + 2);
				if (width >= maxCol)
				{
					sb.append(m_newline);
					width = 0;
				}
				else
					sb.append(", "); //$NON-NLS-1$
			}
			else
				sb.append(m_newline);
		}

		// add a line feed for flow based
		if (flow && width > 0)
			sb.append(m_newline);
	}

	void doInfoFiles()
	{
		try
		{
			StringBuilder sb = new StringBuilder();
            if (hasMoreTokens())
            {
                String arg = nextToken();
                listFilesMatching(sb, arg);
            }
            else
            {
			    buildFileList(sb, false);
            }
			out(sb.toString());
		}
		catch(NullPointerException npe)
		{
			throw new IllegalStateException();
		}
	}

    public void waitForMetaData() throws InProgressException
    {
        // perform a query to see if our metadata has loaded
        int metadatatries = propertyGet(METADATA_ATTEMPTS);
        int maxPerCall = 8;   // cap on how many attempt we make per call

        int tries = Math.min(maxPerCall, metadatatries);
        if (tries > 0)
        {
            int remain = metadatatries - tries; // assume all get used up

            // perform the call and then update our remaining number of attempts
            try
            {
                tries = waitForMetaData(tries);
                remain = metadatatries - tries; // update our used count
            }
            catch(InProgressException ipe)
            {
                propertyPut(METADATA_ATTEMPTS, remain);
				throw ipe;
            }
        }
    }

	/**
	 * Wait for the API to load function names, which
	 * exist in the form of external meta-data.
	 *
	 * Only do this tries times, then give up
	 *
	 * We wait period * attempts
	 */
	public int waitForMetaData(int attempts) throws InProgressException
	{
        int start = attempts;
        int period = propertyGet(METADATA_ATTEMPTS_PERIOD);
		while(attempts > 0)
		{
			// are we done yet?
			if (isMetaDataAvailable())
				break;
			else
				try { attempts--; Thread.sleep(period); } catch(InterruptedException ie) {}
		}

		// throw exception if still not ready
		if (!isMetaDataAvailable())
			throw new InProgressException();

        return start-attempts;  // remaining number of tries
	}

	/**
	 * Ask each swf if metadata processing is complete
	 */
	public boolean isMetaDataAvailable()
	{
		boolean allLoaded = true;
		try 
		{
			// we need to ask the session since our fileinfocache will hide the exception
			SwfInfo[] swfs = m_session.getSwfs();
			for(int i=0; i<swfs.length; i++)
			{
				// check if our processing is finished.
				SwfInfo swf = swfs[i];
				if (swf != null && !swf.isProcessingComplete())
				{
					allLoaded = false;
					break;
				}
			}
		}
		catch(NoResponseException nre)
		{
			// ok we still need to wait for player to read the swd in
			allLoaded = false;
		}

		// count the number of times we checked and it wasn't there
		if (!allLoaded)
		{
			int count = propertyGet(METADATA_NOT_AVAILABLE);
			count++;
			propertyPut(METADATA_NOT_AVAILABLE, count);
		}
		else
		{
			// success so we reset our attempt counter
			propertyPut(METADATA_ATTEMPTS, METADATA_RETRIES);
		}
		return allLoaded;
	}

	void doInfoHandle()
	{
		if (hasMoreTokens())
		{
			// user specified a fault
			String faultName = nextToken();

			// make sure we know about this one
		    if (!m_faultTable.exists(faultName))
				err(getLocalizationManager().getLocalizedTextString("unrecognizedFault")); //$NON-NLS-1$
			else
				listFault(faultName);
		}
		else
		{
			// dump them all
			StringBuilder sb = new StringBuilder();

			appendFaultTitles(sb);

			Object names[]  = m_faultTable.names();
			Arrays.sort(names);

			for(int i=0; i<names.length; i++)
				appendFault(sb, (String)names[i]);

			out ( sb.toString() );
		}
	}

	void doInfoFuncs()
	{
		StringBuilder sb = new StringBuilder();

		String arg = null;

		// we take an optional single arg which specifies a module
		try
		{
			// let's wait a bit for the background load to complete
			waitForMetaData();

			if (hasMoreTokens())
			{
				arg = nextToken();
                int id = arg.equals(".") ? propertyGet(LIST_MODULE) : parseFileArg(-1, arg); //$NON-NLS-1$

				SourceFile m = m_fileInfo.getFile(id, m_activeIsolate);
				listFunctionsFor(sb, m);
			}
			else
			{
				SourceFile[] ar = m_fileInfo.getFileList(m_activeIsolate);
				if (ar == null)
					err(getLocalizationManager().getLocalizedTextString("noSourceFilesFound")); //$NON-NLS-1$
				else
                {
                    for(int i = 0; ar != null && i < ar.length; i++)
                    {
                        SourceFile m = ar[i];
                        listFunctionsFor(sb, m);
                    }
                }
			}

			out(sb.toString());
		}
		catch(NullPointerException npe)
		{
			err(getLocalizationManager().getLocalizedTextString("noFunctionsFound")); //$NON-NLS-1$
		}
		catch(ParseException pe)
		{
			err(pe.getMessage());
		}
		catch(NoMatchException nme)
		{
			err(nme.getMessage());
		}
		catch(AmbiguousException ae)
		{
			err(ae.getMessage());
		}
		catch(InProgressException ipe)
		{
		    err(getLocalizationManager().getLocalizedTextString("functionListBeingPrepared")); //$NON-NLS-1$
		}
	}

	void listFunctionsFor(StringBuilder sb, SourceFile m)
	{
		String[] names = m.getFunctionNames(m_session);
		if (names == null)
			return;

		Arrays.sort(names);

		Map<String, Object> args = new HashMap<String, Object>();
		args.put("sourceFile", m.getName() + "#" + m.getId()); //$NON-NLS-1$ //$NON-NLS-2$
		sb.append(getLocalizationManager().getLocalizedTextString("functionsInSourceFile", args)); //$NON-NLS-1$
		sb.append(m_newline);

        for (int j = 0; j < names.length; j++)
		{
			String fname = names[j];
			sb.append(' ');
			sb.append(fname);
			sb.append(' ');
			sb.append(m.getLineForFunctionName(m_session, fname));
			sb.append(m_newline);
		}
	}

    void listFilesMatching(StringBuilder sb, String match)
    {
        SourceFile[] sourceFiles = m_fileInfo.getFiles(match);

        for (int j = 0; j < sourceFiles.length; j++)
        {
            SourceFile sourceFile = sourceFiles[j];
            sb.append(sourceFile.getName());
			sb.append('#');
			sb.append(sourceFile.getId());
			sb.append(m_newline);
        }
    }

    void doInfoSources()
	{
		try
		{
			StringBuilder sb = new StringBuilder();
			buildFileList(sb, true);
			out(sb.toString());
		}
		catch(NullPointerException npe)
		{
			throw new IllegalStateException();
		}
	}

	void doInfoBreak() throws NotConnectedException
	{
//		waitTilHalted();

		StringBuilder sb = new StringBuilder();
		sb.append("Num Type           Disp Enb Address    What"+m_newline); //$NON-NLS-1$

		int count = breakpointCount();
		for(int i=0; i<count; i++)
		{
			BreakAction b = breakpointAt(i);
			int status = b.getStatus();
			boolean isResolved = (status == BreakAction.RESOLVED);
			Location l = b.getLocation();
			SourceFile file = (l != null) ? l.getFile() : null;
			String funcName = (file == null) ? null : file.getFunctionNameForLine(m_session, l.getLine()) ;
			boolean singleSwf = b.isSingleSwf();
			int cmdCount = b.getCommandCount();
			int hits = b.getHits();
			String cond = b.getConditionString();
			boolean silent = b.isSilent();
			int offset = adjustOffsetForUnitTests((file == null) ? 0 : file.getOffsetForLine(l.getLine()));

			int num = b.getId();
			FieldFormat.formatLong(sb, num, 3);
			sb.append(" breakpoint     "); //$NON-NLS-1$

			if (b.isAutoDisable())
				sb.append("dis  "); //$NON-NLS-1$
			else if (b.isAutoDelete())
				sb.append("del  "); //$NON-NLS-1$
			else
				sb.append("keep "); //$NON-NLS-1$

			if (b.isEnabled())
				sb.append("y   "); //$NON-NLS-1$
			else
				sb.append("n   "); //$NON-NLS-1$

			sb.append("0x"); //$NON-NLS-1$
			FieldFormat.formatLongToHex(sb, offset, 8);
			sb.append(' ');

			if (funcName != null)
			{
				Map<String, Object> args = new HashMap<String, Object>();
				args.put("functionName", funcName); //$NON-NLS-1$
				sb.append(getLocalizationManager().getLocalizedTextString("inFunctionAt", args)); //$NON-NLS-1$
			}

			if (file != null)
			{
				sb.append(file.getName());
				if (isResolved && singleSwf)
				{
					sb.append("#"); //$NON-NLS-1$
					sb.append(file.getId());
				}
				sb.append(':');
				sb.append(l.getLine());
			}
			else
			{
				String expr = b.getBreakpointExpression();
				if (expr != null)
					sb.append(expr);
			}

			switch (status)
			{
			case BreakAction.UNRESOLVED:
				sb.append(getLocalizationManager().getLocalizedTextString("breakpointNotYetResolved")); //$NON-NLS-1$
				break;
			case BreakAction.AMBIGUOUS:
				sb.append(getLocalizationManager().getLocalizedTextString("breakpointAmbiguous")); //$NON-NLS-1$
				break;
			case BreakAction.NOCODE:
				sb.append(getLocalizationManager().getLocalizedTextString("breakpointNoCode")); //$NON-NLS-1$
				break;
			}

			// if a single swf break action then append more info
			if (singleSwf && isResolved)
			{
				try
				{
					SwfInfo info = m_fileInfo.swfForFile(file, l.getIsolateId());
					Map<String, Object> swfArgs = new HashMap<String, Object>();
					swfArgs.put("swf", FileInfoCache.nameOfSwf(info)); //$NON-NLS-1$
					sb.append(getLocalizationManager().getLocalizedTextString("inSwf", swfArgs)); //$NON-NLS-1$
				}
				catch(NullPointerException npe)
				{
					// can't find the swf
					sb.append(getLocalizationManager().getLocalizedTextString("nonRestorable")); //$NON-NLS-1$
				}
			}
			sb.append(m_newline);

			final String INDENT = "        "; //$NON-NLS-1$

			// state our condition if we have one
			if (cond != null && cond.length() > 0)
			{
				sb.append(INDENT);
				Map<String, Object> args = new HashMap<String, Object>();
				args.put("breakpointCondition", cond ); //$NON-NLS-1$
				sb.append(getLocalizationManager().getLocalizedTextString(getLocalizationManager().getLocalizedTextString("stopOnlyIfConditionMet", args))); //$NON-NLS-1$
				sb.append(m_newline);
			}

			// now if its been hit, lets state the fact
			if (hits > 0)
			{
				sb.append(INDENT);
				Map<String, Object> args = new HashMap<String, Object>();
				args.put("count", Integer.toString(hits)); //$NON-NLS-1$
				sb.append(getLocalizationManager().getLocalizedTextString("breakpointAlreadyHit", args)); //$NON-NLS-1$
				sb.append(m_newline);
			}

			// silent?
			if (silent)
			{
				sb.append(INDENT);
				sb.append(getLocalizationManager().getLocalizedTextString("silentBreakpoint")+m_newline); //$NON-NLS-1$
			}

			// now if any commands are trailing then we pump them out
			for(int j=0; j<cmdCount; j++)
			{
				sb.append(INDENT);
				sb.append(b.commandAt(j));
				sb.append(m_newline);
			}
		}
//		}

		int wcount = watchpointCount();
		for(int k = 0; k < wcount; k++)
		{
			WatchAction b = watchpointAt(k);
			int id = b.getId();
			FieldFormat.formatLong(sb, id, 4);

			int flags = b.getKind();
			switch(flags)
			{
				case WatchKind.READ:
					sb.append("rd watchpoint  "); //$NON-NLS-1$
					break;
				case WatchKind.WRITE:
					sb.append("wr watchpoint  "); //$NON-NLS-1$
					break;
				case WatchKind.READWRITE:
				default:
					sb.append("watchpoint     "); //$NON-NLS-1$
					break;
			}

			sb.append("keep "); //$NON-NLS-1$
			sb.append("y   "); //$NON-NLS-1$
			sb.append("           "); //$NON-NLS-1$
			sb.append(b.getExpr());
			sb.append(m_newline);
		}

		int ccount = catchpointCount();
		for (int k = 0; k < ccount; k++)
		{
			CatchAction c = catchpointAt(k);
			int id = c.getId();
			FieldFormat.formatLong(sb, id, 4);

			String typeToCatch = c.getTypeToCatch();
			if (typeToCatch == null)
				typeToCatch = "*"; //$NON-NLS-1$

			sb.append("catch          "); //$NON-NLS-1$
			sb.append("keep "); //$NON-NLS-1$
			sb.append("y   "); //$NON-NLS-1$
			sb.append("           "); //$NON-NLS-1$
			sb.append(typeToCatch);
			sb.append(m_newline);
		}

		out(sb.toString());
	}

	/**
	 * Dump out the state of the execution, either the fact we are running
	 * or the breakpoint we hit.
	 */
	void dumpHaltState(boolean postStep) throws NotConnectedException
	{
		// spit out any event output, if we are to resume after a fault and we're not stepping then we're done.
		processEvents();
//		System.out.println("processEvents = "+m_requestResume);

		//if (m_requestResume && !postStep)
		if (hasAnyPendingResumes() != -1 && !postStep)
			return;

		if (!m_session.isConnected())
		{
			// session is kaput
			out(getLocalizationManager().getLocalizedTextString("sessionTerminated")); //$NON-NLS-1$
			exitSession();
		}
		else
		{
			if (hasAnythingSuspended())
			{
				// capture our break location / information
				StringBuilder sbLine = new StringBuilder();
				dumpBreakLine(postStep, sbLine);

				// Process our breakpoints.
				// Since we can have conditional breakpoints, which the
				// player always breaks for, but we may not want to, the variable
				// m_requestResume may be set after this call.  Additionally,
				// silent may be set for one of two reasons; 1) m_requestResume
				// was set to true in the call or one or more breakpoints that
				// hit contained the keyword silent in their command list.
				//
				StringBuilder sbBreak = new StringBuilder();
				boolean silent = processBreak(postStep, sbBreak, m_activeIsolate);

				StringBuilder sb = new StringBuilder();
				if (silent)
				{
					// silent means we only spit out our current location
					dumpBreakLine(postStep, sb);
				}
				else
				{
					// not silent means we append things like normal
					sb.append(sbLine);
					if (sbLine.length() > 0 && sbLine.charAt(sbLine.length()-1) != '\n')
						sb.append(m_newline);
					sb.append(sbBreak);
				}

				// output whatever was generated 
				if (sb.length() > 0)
					out( sb.toString() );

//				System.out.println("processbreak = "+m_requestResume+",silent="+silent+",reason="+m_session.suspendReason());
			}
			else
			{
				// very bad, set stepping so that we don't trigger a continue on a breakpoint or fault
				out(getLocalizationManager().getLocalizedTextString("playerDidNotStop")); //$NON-NLS-1$
			}
		}
	}

	Location getCurrentLocation()
	{
		return getCurrentLocationIsolate(Isolate.DEFAULT_ID);
	}
	
	Location getCurrentLocationIsolate(int isolateId)
	{
		Location where = null;
		try
		{
			Frame[] ar = m_session.getWorkerSession(isolateId).getFrames();
			propertyPut(CURRENT_FRAME_DEPTH, (ar.length > 0) ? ar.length : 0);
			where = ( (ar.length > 0) ? ar[0].getLocation() : null);
		}
		catch(PlayerDebugException pde)
		{
			// where == null
		}
		return where;
	}

	void dumpBreakLine(boolean postStep, StringBuilder sb) throws NotConnectedException
	{
		int bp = -1;
		String name = getLocalizationManager().getLocalizedTextString("unknownFilename"); //$NON-NLS-1$
		int line = -1;

		// clear our current frame display
		propertyPut(DISPLAY_FRAME_NUMBER, 0);
		
		int targetIsolate = getLastStoppedIsolate();
		boolean activeIsolateChanged = (m_activeIsolate != targetIsolate);
		m_activeIsolate = targetIsolate;
		propertyPut(LIST_WORKER, targetIsolate);

		/* dump a context line to the console */
		Location l = getCurrentLocationIsolate(targetIsolate);

		// figure out why we stopped
		int reason = SuspendReason.Unknown;
		try { reason = m_session.getWorkerSession(targetIsolate).suspendReason(); } catch(PlayerDebugException pde) {}

		// then see if it because of a swfloaded event
		if( reason == SuspendReason.ScriptLoaded)
		{
            // since the player takes a long time to provide swf/swd, try 80 * 250ms = ~20s
            if (propertyGet(METADATA_ATTEMPTS) > 0)
			    try { waitForMetaData(80); } catch(InProgressException ipe) { }

            m_fileInfo.setDirty();
            m_fileInfo.getSwfsIsolate(targetIsolate);
            //propertyPut(LIST_MODULE, m_fileInfo.getFakeId(m_fileInfo.getFile(1, targetIsolate)));
			processEvents();
            propagateBreakpoints(targetIsolate);
            propertyPut(LIST_LINE, 1);
            propertyPut(LIST_WORKER, targetIsolate);
            propertyPut(LIST_MODULE, 1);
            sb.append(getLocalizationManager().getLocalizedTextString("additionalCodeLoaded")); //$NON-NLS-1$
            if ( activeIsolateChanged ) {
            	sb.append(m_newline + getLocalizationManager().getLocalizedTextString("workerChanged")+ " " + (targetIsolate - 1) + m_newline); //$NON-NLS-1$ //$NON-NLS-2$
            }
            sb.append(m_newline);

			if (resolveBreakpoints(sb))
				sb.append(getLocalizationManager().getLocalizedTextString("setAdditionalBreakpoints")+m_newline); //$NON-NLS-1$
			else
				sb.append(getLocalizationManager().getLocalizedTextString("fixBreakpoints")+m_newline); //$NON-NLS-1$
			
			setPromptState(InitialPromptState.SHOWN_ONCE, targetIsolate);
		}
		else if ( l == null || l.getFile() == null )
		{
			
			if ( activeIsolateChanged ) {
				sb.append(m_newline + getLocalizationManager().getLocalizedTextString("workerChanged")+ " " + (targetIsolate - 1) + m_newline); 
			}
			
			// no idea where we are ?!?
			propertyPut(LAST_FRAME_DEPTH, 0);
			sb.append(getLocalizationManager().getLocalizedTextString("executionHalted")); //$NON-NLS-1$
			sb.append(' ');

			/** disable this line (and enable the one after) if implementation Extensions are not provided */
			appendBreakInfo(sb, m_activeIsolate);
			//sb.append("unknown location");
		}
		else
		{
			if ( activeIsolateChanged ) {
				sb.append(m_newline + getLocalizationManager().getLocalizedTextString("workerChanged")+ " " + (targetIsolate - 1) + m_newline); 
			}
			
			SourceFile file = l.getFile();
			name = file.getName();
			line = l.getLine();
			String funcName = file.getFunctionNameForLine(m_session, line) ;

			// where were we last time
			int lastModule = propertyGet(LIST_MODULE);
			int lastDepth = propertyGet(LAST_FRAME_DEPTH);

			int thisModule = file.getId();
			int thisDepth = propertyGet(CURRENT_FRAME_DEPTH);  // triggered via getCurrentLocation()

			// mark where we stopped
			propertyPut(LAST_FRAME_DEPTH, thisDepth);

			// if we have changed our context or we are not spitting out source then dump our location
			if (!postStep || lastModule != thisModule || lastDepth != thisDepth )
			{
				// is it a fault?
				String reasonForHalting;
				if ( reason == SuspendReason.Fault || reason == SuspendReason.StopRequest)
				{
					StringBuilder s = new StringBuilder();
					appendReason(s, reason);
					reasonForHalting = s.toString();
				}
				// if its a breakpoint add that information
				else if ( (bp = enabledBreakpointIndexOf(l)) > -1 )
				{
					Map<String, Object> args = new HashMap<String, Object>();
					args.put("breakpointNumber", Integer.toString(breakpointAt(bp).getId())); //$NON-NLS-1$
					reasonForHalting = getLocalizationManager().getLocalizedTextString("hitBreakpoint", args); //$NON-NLS-1$
				}
				else
				{
					reasonForHalting = getLocalizationManager().getLocalizedTextString("executionHalted"); //$NON-NLS-1$
				}

				Map<String, Object> args = new HashMap<String, Object>();
				args.put("reasonForHalting", reasonForHalting); //$NON-NLS-1$
				args.put("fileAndLine", name + ':' + line); //$NON-NLS-1$
				String formatString;
				if (funcName != null)
				{
					args.put("functionName", funcName); //$NON-NLS-1$
					formatString = "haltedInFunction"; //$NON-NLS-1$
				}
				else
				{
					formatString = "haltedInFile"; //$NON-NLS-1$
				}
				sb.append(getLocalizationManager().getLocalizedTextString(formatString, args));

				if (!m_fullnameOption) 
					sb.append(m_newline);				
			}

            // set current listing poistion and emit emacs trigger
            setListingPosition(thisModule, line, targetIsolate);

			// dump our source line if not in emacs mode
			if (!m_fullnameOption)
				appendSource(sb, file.getId(), line, file.getLine(line), false);
		}
	}

	private int getLastStoppedIsolate() {
	int targetIsolate = Isolate.DEFAULT_ID;
		
		if (m_breakIsolates.size() > 0) {
			targetIsolate = m_breakIsolates.get(m_breakIsolates.size() - 1);
		}
		return targetIsolate;
	}

	void appendFullnamePosition(StringBuilder sb, SourceFile file, int lineNbr)
	{
        // fullname option means we dump 'path:line:col?:offset', which is used for emacs !
		String name = file.getFullPath();
		if (name.startsWith("file:/")) //$NON-NLS-1$
			name = name.substring(6);

		// Ctrl-Z Ctrl-Z
		sb.append('\u001a');
		sb.append('\u001a');

		sb.append(name);
		sb.append(':');
		sb.append(lineNbr);
		sb.append(':');
		sb.append('0');
		sb.append(':');
		sb.append("beg"); //$NON-NLS-1$
		sb.append(':');
		sb.append('0');
	}

	// pretty print a trace statement to the console
	void dumpTraceLine(String s)
	{
		StringBuilder sb = new StringBuilder();
		sb.append("[trace] "); //$NON-NLS-1$
		sb.append(s);
		out(sb.toString());
	}

	// pretty print a fault statement to the console
	void dumpFaultLine(FaultEvent e)
	{
		StringBuilder sb = new StringBuilder();

		// use a slightly different format for ConsoleErrorFaults
		if (e instanceof ConsoleErrorFault)
		{
			sb.append(getLocalizationManager().getLocalizedTextString("linePrefixWhenDisplayingConsoleError")); //$NON-NLS-1$
			sb.append(' ');
			sb.append(e.information);
		}
		else
		{
			String name = e.name();
			sb.append(getLocalizationManager().getLocalizedTextString("linePrefixWhenDisplayingFault")); //$NON-NLS-1$
			sb.append(' ');
			sb.append(name);
			if (e.information != null && e.information.length() > 0)
			{
				sb.append(getLocalizationManager().getLocalizedTextString("informationAboutFault")); //$NON-NLS-1$
				sb.append(e.information);
			}
		}
		out( sb.toString() );
	}

    /**
     * Called when a swf has been loaded by the player
     * @param e event documenting the load
     */
    void handleSwfLoadedEvent(SwfLoadedEvent e)
    {
        // first we dump out a message that displays we have loaded a swf
        dumpSwfLoadedLine(e);
    }

	// pretty print a SwfLoaded statement to the console
	void dumpSwfLoadedLine(SwfLoadedEvent e)
	{
		// now rip off any trailing ? options
		int at = e.path.lastIndexOf('?');
		String name = (at > -1) ? e.path.substring(0, at) : e.path;

		StringBuilder sb = new StringBuilder();
		sb.append(getLocalizationManager().getLocalizedTextString("linePrefixWhenSwfLoaded")); //$NON-NLS-1$
		sb.append(' ');
		sb.append(name);
		sb.append(" - "); //$NON-NLS-1$

		Map<String, Object> args = new HashMap<String, Object>();
		args.put("size", NumberFormat.getInstance().format(e.swfSize)); //$NON-NLS-1$
		sb.append(getLocalizationManager().getLocalizedTextString("sizeAfterDecompression", args)); //$NON-NLS-1$
		out(sb.toString());
	}

    /**
     * Propagate current breakpoints to the newly loaded swf.
     */
    void propagateBreakpoints(int isolateId) throws NotConnectedException
    {
		// get the newly added swf, which lands at the end list
		SwfInfo[] swfs = m_fileInfo.getSwfsIsolate(isolateId);
		SwfInfo swf = (swfs.length > 1) ? swfs[swfs.length-1] : null;

		// now walk through all breakpoints propagating the 
		// the break for each source and line number we
		// find in the new swf
		int size = m_breakpoints.size();
		for (int i = 0; (swf != null) && i < size; i++)
		{
			// dont do this for single swf breakpoints
			BreakAction bp = breakpointAt(i);
			if (bp.isSingleSwf())
				continue;
			if (bp.getStatus() != BreakAction.RESOLVED)
				continue;

			try
			{
				Location l = bp.getLocation();
				int line = l.getLine();
				SourceFile f = l.getFile();
				Location newLoc = findAndEnableBreak(swf, f, line);
				if (newLoc != null)
					bp.addLocation(newLoc);
			}
			catch(InProgressException ipe)
			{
				if (breakpointCount() > 0)
				{
					Map<String, Object> args = new HashMap<String, Object>();
					args.put("breakpointNumber", Integer.toString(bp.getId())); //$NON-NLS-1$
					out(getLocalizationManager().getLocalizedTextString("breakpointNotPropagated", args)); //$NON-NLS-1$
				}
			}
		}
    }

	/**
	 * Perform the tasks need for when a swf is unloaded
	 * the player
	 */
	void handleSwfUnloadedEvent(SwfUnloadedEvent e)
	{
		// print out the notification
		dumpSwfUnloadedLine(e);
	}

	// pretty print a SwfUnloaded statement to the console
	void dumpSwfUnloadedLine(SwfUnloadedEvent e)
	{
		// now rip off any trailing ? options
		int at = e.path.lastIndexOf('?');
		String name = (at > -1) ? e.path.substring(0, at) : e.path;

		StringBuilder sb = new StringBuilder();
		sb.append(getLocalizationManager().getLocalizedTextString("linePrefixWhenSwfUnloaded")); //$NON-NLS-1$
		sb.append(' ');
		sb.append(name);
		out(sb.toString());
	}

	void doContinue() throws NotConnectedException
	{
		//int stoppedIsolate = getLastStoppedIsolate();
		int stoppedIsolate = m_activeIsolate;
		waitTilHalted(stoppedIsolate);

		// this will trigger a resume when we get back to the main loop
		//m_requestResume = true;
		setRequestResume(true, stoppedIsolate);
		m_repeatLine = m_currentLine;
	}
	
	boolean hasAnythingSuspended() throws NotConnectedException {
		boolean hasAnythingSuspended = false;
		for (Integer id : m_breakIsolates) {
			if (m_session.getWorkerSession(id).isSuspended()) {
				hasAnythingSuspended = true;
				break;
			}
		}
		return hasAnythingSuspended;
	}
	
	int hasAnyPendingResumes() throws NotConnectedException {
		int rid = -1;
		if (m_mainState.m_requestResume)
			return Isolate.DEFAULT_ID;
		for (Integer id : m_breakIsolates) {
			if (getIsolateState(id).m_requestResume) {
				rid = id;
				break;
			}
		}
		return rid;
	}
	
	/**
	 * Returns the first isolate's id for which we need to keep showing prompts.
	 * 
	 * @return The isolate id
	 * @throws NotConnectedException
	 */
	int hasPendingInitialPrompts() throws NotConnectedException {
		int rid = -1;
		for (Integer id : m_breakIsolates) {
			if (getPromptState(id) != InitialPromptState.DONE) {
				rid = id;
				break;
			}
		}
		return rid;
	}

	/**
	 * Our main loop when the player is off running
	 */
	public void runningLoop() throws NoResponseException, NotConnectedException
	{
		int update = propertyGet(UPDATE_DELAY);
		boolean nowait = (propertyGet(NO_WAITING) == 1) ? true : false;  // DEBUG ONLY; do not document
		boolean stop = false;
		boolean noConnection = !haveConnection();
		boolean hasAnythingSuspended = false;
		int targetIsolate = Isolate.DEFAULT_ID;
		if (!noConnection) {
			hasAnythingSuspended = hasAnythingSuspended();
		}

		if (hasAnythingSuspended) {
			if (m_breakIsolates.size() > 0) {
				targetIsolate = m_breakIsolates.get(m_breakIsolates.size() - 1);
			}
		}
		// not there, not connected or already halted and no pending resume requests => we are done
		//if (noConnection || (hasAnythingSuspended && !m_requestResume) )
		if (noConnection || (hasAnythingSuspended && hasAnyPendingResumes() == -1) )
		{
			processEvents();
			stop = true;
			
			if(!noConnection) {
				/** At this point, some isolate is in suspended state and will be until a resume 
				 *  is requested via the prompt. We thus check for any pending prompts to be displayed 
				 *  for freshly loaded swfs. If any, we switch to that worker and prompt the user to set 
				 *  any break points.  */
				int pendingPromptIsolate = -1;
				if ( m_lastPromptIsolate != -1 && ( getPromptState(m_lastPromptIsolate) != InitialPromptState.DONE ) ) {
					pendingPromptIsolate = m_lastPromptIsolate;
				} else {
					pendingPromptIsolate = hasPendingInitialPrompts();
				}
				if ( pendingPromptIsolate != -1) {
					dumpInitialPrompt(pendingPromptIsolate);
				}
			}
		}

	    while(!stop)
		{
			// allow keyboard input
			if (!nowait)
				m_keyboardReadRequest = true;
			int pendingResumeId = hasAnyPendingResumes();
			if (pendingResumeId != -1)
			{
				// resume execution (request fulfilled) and look for keyboard input
				try
				{
					IsolateSession workerSession = m_session.getWorkerSession(pendingResumeId);
					//if (m_stepResume)
					if (getStepResume(pendingResumeId))
						workerSession.stepContinue();
					else {
						workerSession.resume();
					}
					/** The user is done setting initial breakpoints for this isolate,
					 *  clear any pending initial prompts */
					setPromptState(InitialPromptState.DONE, pendingResumeId);
					removeBreakIsolate(pendingResumeId);
				}
				catch(NotSuspendedException nse)
				{
					err(getLocalizationManager().getLocalizedTextString("playerAlreadyRunning")); //$NON-NLS-1$
				}

				setRequestResume(false, pendingResumeId);
				setRequestHalt(false, pendingResumeId);
				setStepResume(false, pendingResumeId);
//				m_requestResume = false;
//				m_requestHalt = false;
//				m_stepResume = false;
			}

			// sleep for a bit, then process our events.
			try { Thread.sleep(update); } catch(InterruptedException ie) {}
			processEvents();

			// lost connection?
			if (!haveConnection())
			{
				stop = true;
				dumpHaltState(false);
			}
			else if (hasAnythingSuspended())
			{
				/**
				 * We have stopped for some reason.  Now for all cases, but conditional
				 * breakpoints, we should be done.  For conditional breakpoints it
				 * may be that the condition has turned out to be false and thus
				 * we need to continue
				 */

				/**
				 * Now before we do this see, if we have a valid break reason, since
				 * we could be still receiving incoming messages, even though we have halted.
				 * This is definately the case with loading of multiple SWFs.  After the load
				 * we get info on the swf.
				 */
				if (m_breakIsolates.size() > 0) {
					targetIsolate = m_breakIsolates.get(m_breakIsolates.size() - 1);
				}
				else {
					targetIsolate = Isolate.DEFAULT_ID;
				}
				int tries = 3;
				IsolateSession workerSession = m_session.getWorkerSession(targetIsolate);
				while (tries-- > 0 && workerSession.suspendReason() == SuspendReason.Unknown)
					try { Thread.sleep(100); processEvents(); } catch(InterruptedException ie) {}

				dumpHaltState(false);
				//if (!m_requestResume)
				if (!getRequestResume(targetIsolate))
					stop = true;
			}
			else if (nowait)
			{
				stop = true;  // for DEBUG only
			}
			else
			{
				/**
				 * We are still running which is fine.  But let's see if the user has
				 * tried to enter something on the keyboard.  If so, then we need to
				 * stop
				 */
				if (!m_keyboardInput.isEmpty() && System.getProperty("fdbunit")==null) //$NON-NLS-1$
				{
					// flush the queue and prompt the user if they want us to halt
					m_keyboardInput.clear();
					try
					{
						if (yesNoQuery(getLocalizationManager().getLocalizedTextString("doYouWantToHalt"))) //$NON-NLS-1$
						{
							out(getLocalizationManager().getLocalizedTextString("attemptingToHalt")); //$NON-NLS-1$
							IsolateSession workerSession = m_session.getWorkerSession(m_activeIsolate);
							workerSession.suspend();
//							m_session.suspend();
							getIsolateState(m_activeIsolate).m_requestHalt = true;

							// no connection => dump state and end
							if (!haveConnection())
							{
								dumpHaltState(false);
								stop = true;
							}
							else if (!workerSession.isSuspended())
								err(getLocalizationManager().getLocalizedTextString("couldNotHalt")); //$NON-NLS-1$
						}
					}
					catch(IllegalArgumentException iae)
					{
						out(getLocalizationManager().getLocalizedTextString("escapingFromDebuggerPendingLoop")); //$NON-NLS-1$
						propertyPut(NO_WAITING, 1);
						stop = true;
					}
					catch(IOException io)
					{
						Map<String, Object> args = new HashMap<String, Object>();
						args.put("error", io.getMessage()); //$NON-NLS-1$
						err(getLocalizationManager().getLocalizedTextString("continuingDueToError", args)); //$NON-NLS-1$
					}
					catch(SuspendedException se)
					{
						// lucky us, already stopped
					}
				}
			}
//		System.out.println("doContinue resume="+m_requestResume+",isSuspended="+m_session.isSuspended());
		}

		// DEBUG ONLY: if we are not waiting then process some events
		if (nowait)
			processEvents();
	}

	/**
	 *  Does a few of things - 
	 * 		1) Sets the target worker as 'active'.
	 * 		2) Propagates any breakpoints already set which are relevant to the target worker.
	 * 		3) Outputs messages indicating additional code load and worker switch.
	 * 		4) Sets {@link DebugCLIIsolateState#m_promptState} as {@link InitialPromptState#SHOWN_ONCE} if 
	 * 		   the prompt hasn't been shown for this worker before.
	 */
	private void dumpInitialPrompt(int targetIsolate) throws NotConnectedException{
		boolean activeIsolateChanged = ( m_activeIsolate != targetIsolate );
		m_activeIsolate = targetIsolate;
		
		if ( activeIsolateChanged ) {
			propertyPut(LIST_WORKER, targetIsolate);
			propertyPut(LIST_LINE, 1);
			propertyPut(LIST_MODULE, 1);
			propagateBreakpoints(targetIsolate);
		}
		
        StringBuilder sb = new StringBuilder();
        if (getPromptState(targetIsolate) == InitialPromptState.NEVER_SHOWN) {
        	sb.append(getLocalizationManager().getLocalizedTextString("additionalCodeLoaded")); //$NON-NLS-1$
        	sb.append(m_newline + getLocalizationManager().getLocalizedTextString("workerChanged")+ " " + (targetIsolate - 1) + m_newline); //$NON-NLS-1$ //$NON-NLS-2$
        	sb.append(m_newline);
        	setPromptState(InitialPromptState.SHOWN_ONCE, targetIsolate);
        }

		if (resolveBreakpoints(sb))
			sb.append(getLocalizationManager().getLocalizedTextString("setAdditionalBreakpoints")+m_newline); //$NON-NLS-1$
		else
			sb.append(getLocalizationManager().getLocalizedTextString("fixBreakpoints")+m_newline); //$NON-NLS-1$
		
		// output whatever has to be
		if (sb.length() > 0)
			out( sb.toString() );
		
	}

	private void removeBreakIsolate(int targetIsolate) {
		for (int i = 0; i < m_breakIsolates.size();i++) {
			int id = m_breakIsolates.get(i);
			if (id == targetIsolate) {
				m_breakIsolates.remove(i);
				break;
			}
		}
	}

	/**
	 * Bring the listing location back to the current frame
	 */
	void doHome()
	{
		try
		{
			Location l = getCurrentLocationIsolate(m_activeIsolate);
			SourceFile file = l.getFile();
			int module = file.getId();
			int line = l.getLine();
			int worker = l.getIsolateId();

			// now set it
            setListingPosition(module, line, worker);
		}
		catch(NullPointerException npe)
		{
			err(getLocalizationManager().getLocalizedTextString("currentLocationUnknown")); //$NON-NLS-1$
		}
	}

	// Dump a source line of text to the display
	void dumpStep() throws NotConnectedException
	{
		dumpHaltState(true);
	}

	/**
	 * Simple interface used with stepWithTimeout().  Implementors of this interface
	 * are expected to call one of these function: Session.stepInto(), Session.stepOver(),
	 * Session.stepOut(), or Session.stepContinue().
	 */
	private interface AnyKindOfStep
	{
		public void step() throws PlayerDebugException;
	}

	/**
	 * Helper function to do a stepInto, stepOver, stepOut, or stepContinue,
	 * and then to block (processing events) until either the step has completed
	 * or it has timed out.
	 */
	private void stepWithTimeout(AnyKindOfStep step, int isolateId) throws PlayerDebugException
	{
		int timeout = m_session.getPreference(SessionManager.PREF_RESPONSE_TIMEOUT);
		long timeoutTime = System.currentTimeMillis() + timeout;

		step.step();
		IsolateSession workerSession = m_session.getWorkerSession(isolateId);
		while (System.currentTimeMillis() < timeoutTime && !workerSession.isSuspended())
		{
			processEvents();
			if (!m_session.isSuspended())
			{
				try { Thread.sleep(1); } catch (InterruptedException e) { }
			}
		}
		if (System.currentTimeMillis() >= timeoutTime && !workerSession.isSuspended())
			throw new NoResponseException(timeout);
	}

	private boolean allowedToStep(int isolateId) throws NotConnectedException
	{
		int suspendReason = m_session.getWorkerSession(isolateId).suspendReason();
		if (suspendReason == SuspendReason.ScriptLoaded)
		{
			err(getLocalizationManager().getLocalizedTextString("cannotStep")); //$NON-NLS-1$
			return false;
		}

		return true;
	}

	/**
	 * Perform step into, optional COUNT parameter
	 */
	void doStep() throws PlayerDebugException
	{
		waitTilHalted(m_activeIsolate);

		if (!allowedToStep(m_activeIsolate))
			return;
		
		int count = 1;
		if (hasMoreTokens())
			count = nextIntToken();
		DebugCLIIsolateState state = getIsolateState(m_activeIsolate);
		while(count-- > 0)
		{
			stepWithTimeout(new AnyKindOfStep() {
				public void step() throws PlayerDebugException
				{
					m_session.getWorkerSession(m_activeIsolate).stepInto();
				}
			}, m_activeIsolate);

			for (;;)
			{
				dumpStep();

				if (state.m_requestResume) // perhaps we hit a conditional breakpoint
				{
					state.m_requestResume = false;
					stepWithTimeout(new AnyKindOfStep() {
						public void step() throws PlayerDebugException
						{
							m_session.getWorkerSession(m_activeIsolate).stepContinue();
						}
					}, m_activeIsolate);
				}
				else
				{
					break;
				}
			}
		}

		m_repeatLine = m_currentLine;
	}

	/**
	 * Perform step over, optional COUNT parameter
	 */
	void doNext() throws PlayerDebugException
	{
		waitTilHalted(m_activeIsolate);

		if (!allowedToStep(m_activeIsolate))
			return;
		
		int count = 1;
		if (hasMoreTokens())
			count = nextIntToken();
		DebugCLIIsolateState state = getIsolateState(m_activeIsolate);
		try
		{
			while(count-- > 0)
			{
				stepWithTimeout(new AnyKindOfStep() {
					public void step() throws PlayerDebugException
					{
						m_session.getWorkerSession(m_activeIsolate).stepOver();
					}
				},m_activeIsolate);

				for (;;)
				{
					dumpStep();

					if (state.m_requestResume) // perhaps we hit a conditional breakpoint
					{
						state.m_requestResume = false;
						stepWithTimeout(new AnyKindOfStep() {
							public void step() throws PlayerDebugException
							{
								m_session.getWorkerSession(m_activeIsolate).stepContinue();
							}
						},m_activeIsolate);
					}
					else
					{
						break;
					}
				}
			}
		}
		catch(NoResponseException nre)
		{
			if (count > 0)
			{
				Map<String, Object> args = new HashMap<String, Object>();
				args.put("count", Integer.toString(count)); //$NON-NLS-1$
				err(getLocalizationManager().getLocalizedTextString("abortingStep", args)); //$NON-NLS-1$
			}
		}

		m_repeatLine = m_currentLine;
	}

	/**
	 * Perform step out
	 */
	void doFinish() throws PlayerDebugException
	{
		waitTilHalted(m_activeIsolate);

		if (!allowedToStep(m_activeIsolate))
			return;
		DebugCLIIsolateState state = getIsolateState(m_activeIsolate);
		try
		{
			// make sure we have another frame?
			int depth = propertyGet(CURRENT_FRAME_DEPTH);
			if (depth < 2)
				err(getLocalizationManager().getLocalizedTextString("finishCommandNotMeaningfulOnOutermostFrame")); //$NON-NLS-1$
			else
			{
				stepWithTimeout(new AnyKindOfStep() {
					public void step() throws PlayerDebugException
					{
						m_session.getWorkerSession(m_activeIsolate).stepOut();
					}
				},m_activeIsolate);

				for (;;)
				{
					dumpStep();

					if (state.m_requestResume) // perhaps we hit a conditional breakpoint
					{
						state.m_requestResume = false;
						stepWithTimeout(new AnyKindOfStep() {
							public void step() throws PlayerDebugException
							{
								m_session.getWorkerSession(m_activeIsolate).stepContinue();
							}
						},m_activeIsolate);
					}
					else
					{
						break;
					}
				}

				m_repeatLine = m_currentLine;
			}
		}
		catch(NullPointerException npe)
		{
			err(getLocalizationManager().getLocalizedTextString("finishCommandNotMeaningfulWithoutStack")); //$NON-NLS-1$
		}
	}

	/**
	 * Delete a breakpoint, very similar logic to disable.
	 */
	void doDelete() throws IOException, AmbiguousException, NotConnectedException
	{
		waitTilHalted(m_activeIsolate);

		try
		{
			if (!hasMoreTokens())
			{
				// no args means delete all breakpoints, last chance...
				if (yesNoQuery(getLocalizationManager().getLocalizedTextString("askDeleteAllBreakpoints"))) //$NON-NLS-1$
				{
					int count = breakpointCount();
					for(int i=count-1; i>-1; i--)
						removeBreakpointAt(i);

					removeAllWatchpoints();
					removeAllCatchpoints();
				}
			}
			else
			{
				// optionally specify  'display' or 'breakpoint'
				String arg = nextToken();
				int cmd = disableCommandFor(arg);
				int id = -1;
				if (cmd == CMD_DISPLAY)
					doUnDisplay();
				else
				{
					if (cmd == CMD_BREAK)
						id = nextIntToken();  // ignore and get next number token
					else
						id = Integer.parseInt(arg);

					do
					{
						try
						{
							int at = breakpointIndexOf(id);
							if(at > -1)
							{
								removeBreakpointAt(at);
							}
							else
							{
								at = watchpointIndexOf(id);
								if (at > -1)
								{
									removeWatchpointAt(at);
								}
								else
								{
									at = catchpointIndexOf(id);
									removeCatchpointAt(at);
								}
							}
						}
						catch(IndexOutOfBoundsException iob)
						{
							Map<String, Object> args = new HashMap<String, Object>();
							args.put("breakpointNumber", m_currentToken); //$NON-NLS-1$
							err(getLocalizationManager().getLocalizedTextString("noBreakpointNumber", args)); //$NON-NLS-1$
						}

						if (hasMoreTokens())
							id = nextIntToken();
						else
							id = -1;

						// keep going till we're blue in the face; also note that we cache'd a copy of locations
						// so that breakpoint numbers are consistent.
					}
					while( id > -1 );
				}
			}
		}
		catch(NumberFormatException nfe)
		{
			Map<String, Object> args = new HashMap<String, Object>();
			args.put("token", m_currentToken); //$NON-NLS-1$
			err(getLocalizationManager().getLocalizedTextString("badBreakpointNumber", args)); //$NON-NLS-1$
		}
		catch(NullPointerException npe)
		{
			err(getLocalizationManager().getLocalizedTextString("commandFailed")); //$NON-NLS-1$
		}
	}

	/**
	 * Set a breakpoint
	 */
	void doBreak() throws NotConnectedException
	{
		int isolateId = propertyGet(LIST_WORKER);
		/* wait a bit if we are not halted */
		waitTilHalted(isolateId);

        int module = propertyGet(LIST_MODULE);
		int line = propertyGet(LIST_LINE);
		
        String arg = null;

		/* currentXXX may NOT be invalid! */
		try
		{
			if (hasMoreTokens())
			{
                arg = nextToken();
                int[] result = parseLocationArg(module, line, arg, isolateId);
                module = result[0];
                line = result[1];
			}
			else
			{
				// no parameter mean use current location;  null pointer if nothing works
				Location l = getCurrentLocationIsolate(isolateId);
				SourceFile file = l.getFile();
				module = file.getId();
				line = l.getLine();
			}

//			// check to see if there are any existing breakpoints at this file/line
//			LinkedList existingBreakpoints = new LinkedList();
//			int start = 0;
//			for (;;)
//			{
//				int bp = breakpointIndexOf(module, line, start, true);
//				if (bp == -1)
//					break; // no more matches
//				boolean isEnabled = breakpointAt(bp).isEnabled();
//				existingBreakpoints.add("" + bp + (isEnabled ? "" : " (disabled)"));
//			}
//			if (existingBreakpoints.size() > 0)
//			{
//				String
//			}

			// go off; create it and set it
            BreakAction b = addBreakpoint(module, line, isolateId);  // throws npe if not able to set
            Location l = b.getLocation();

			int which = b.getId();
			String name = l.getFile().getName();
			int offset  = adjustOffsetForUnitTests(l.getFile().getOffsetForLine(line));

			Map<String, Object> args = new HashMap<String, Object>();
			args.put("breakpointNumber", Integer.toString(which)); //$NON-NLS-1$
			args.put("file", name); //$NON-NLS-1$
			args.put("line", Integer.toString(line)); //$NON-NLS-1$
			String formatString;
			if (offset != 0)
			{
				args.put("offset", "0x" + Integer.toHexString(offset)); //$NON-NLS-1$ //$NON-NLS-2$
				formatString = "createdBreakpointWithOffset"; //$NON-NLS-1$
			}
			else
			{
				formatString = "createdBreakpoint"; //$NON-NLS-1$
			}
			out(getLocalizationManager().getLocalizedTextString(formatString, args));

			// worked so add it to our tracking state
			propertyPut(BPNUM, which);
		}
		catch(ParseException pe)
		{
			err(pe.getMessage());
		}
		catch(AmbiguousException ae)
		{
			err(ae.getMessage());
		}
		catch(NoMatchException nme)
		{
			// We couldn't find a function name or filename which matched what
			// the user entered.  Do *not* fail; instead, just save this breakpoint
			// away, and later, as more ABCs get loaded from the SWF, we may be
			// able to resolve this breakpoint.
			BreakAction b = addUnresolvedBreakpoint(arg, m_activeIsolate);

			Map<String, Object> args = new HashMap<String, Object>();
			args.put("breakpointNumber", Integer.toString(b.getId())); //$NON-NLS-1$
			out(getLocalizationManager().getLocalizedTextString("breakpointCreatedButNotYetResolved", args)); //$NON-NLS-1$

			// add it to our tracking state
			propertyPut(BPNUM, b.getId());
		}
		catch(NullPointerException npe)
		{
			String filename;
			try
			{
				filename = m_fileInfo.getFile(module, isolateId).getName() + "#" + module; //$NON-NLS-1$
			}
			catch (Exception e)
			{
				Map<String, Object> args = new HashMap<String, Object>();
				args.put("fileNumber", Integer.toString(module)); //$NON-NLS-1$
				filename = getLocalizationManager().getLocalizedTextString("fileNumber", args); //$NON-NLS-1$
			}

			Map<String, Object> args = new HashMap<String, Object>();
			args.put("filename", filename); //$NON-NLS-1$
			args.put("line", Integer.toString(line)); //$NON-NLS-1$
			err(getLocalizationManager().getLocalizedTextString("breakpointNotSetNoCode", args)); //$NON-NLS-1$
		}
	}

	/**
	 * Clear a breakpoint
	 */
	void doClear() throws NotConnectedException
	{
        int module = propertyGet(LIST_MODULE);
		int line = propertyGet(LIST_LINE);
		int isolateId = propertyGet(LIST_WORKER);
        String arg = null;

		/* wait a bit if we are not halted */
		waitTilHalted(m_activeIsolate);

		/* currentXXX may NOT be invalid! */
		try
		{
			if (hasMoreTokens())
			{
                arg = nextToken();
                int[] result = parseLocationArg(module, line, arg, isolateId);
                module = result[0];
                line = result[1];
			}

			// map the breakpoint to location and then delete it
			removeBreakpoint(module, line);
		}
		catch(ParseException pe)
		{
			err(pe.getMessage());
		}
		catch(NoMatchException nme)
		{
			if (removeUnresolvedBreakpoint(arg) == null)
				err(getLocalizationManager().getLocalizedTextString("breakpointLocationUnknown")); //$NON-NLS-1$
		}
		catch(AmbiguousException ae)
		{
			err(ae.getMessage());
		}
		catch(ArrayIndexOutOfBoundsException aio)
		{
			// means no breakpoint at this location
			err(getLocalizationManager().getLocalizedTextString("breakpointLocationUnknown")); //$NON-NLS-1$
		}
		catch(NullPointerException npe)
		{
			err(getLocalizationManager().getLocalizedTextString("breakpointNotCleared")); //$NON-NLS-1$
		}
	}

	/**
	 * Remove the breakpoint from our table and then determine
	 */
	BreakAction removeBreakpoint(int fileId, int line) throws ArrayIndexOutOfBoundsException, NotConnectedException
	{
		int at = breakpointIndexOf(fileId, line);
		return removeBreakpointAt(at);
	}

	BreakAction removeUnresolvedBreakpoint(String unresolvedLocation) throws NotConnectedException
	{
		int size = breakpointCount();
		for(int i=0; i<size; i++)
		{
			BreakAction b = breakpointAt(i);
			String s = b.getBreakpointExpression();
			if (s != null && s.equals(unresolvedLocation))
				return removeBreakpointAt(i);
		}
		return null;
	}

	BreakAction removeBreakpointAt(int at) throws ArrayIndexOutOfBoundsException, NotConnectedException
	{
		BreakAction a = breakpointAt(at);
//		if (isolateId == Isolate.DEFAULT_ID)
			m_breakpoints.removeElementAt(at);
//		else
//			getIsolateState(isolateId).m_breakpoints.removeElementAt(at);
		
		if (a.getStatus() == BreakAction.RESOLVED)
			breakDisableRequest(a.getLocations());
		return a;
	}

    /**
     * Attempt to create new breakpoint at the given file and line. It will be set
     * @param fileId source file identifier
     * @param line line number
     * @return object associated with breakpoint
     */
    BreakAction addBreakpoint(int fileId, int line, int isolateId) throws NotConnectedException, NullPointerException
    {
		// use fileId SourceFile to denote the name of file in which we wish to set a breakpoint    	
    	SourceFile f = m_fileInfo.getFile(fileId, isolateId);
      
        
		LocationCollection col = enableBreak(f, line, isolateId);

        BreakAction b = new BreakAction(col);  //  throws NullPointerException if collection is null
        b.setEnabled(true);
		b.setSingleSwf(m_fileInfo.isSwfFilterOn());
        breakpointAdd(b);
        return b;
    }
	
	/**
	 * Create a new, *unresolved* breakpoint.  Unresolved means we weren't able to
	 * parse the location string, presumably because the filename to which it refers
	 * has not yet been loaded.
	 * @param unresolvedLocation the breakpoint location, exactly as typed by the user
	 * @return object associated with breakpoint
	 */
	private BreakAction addUnresolvedBreakpoint(String unresolvedLocation, int isolateId)
	{
		BreakAction b = new BreakAction(unresolvedLocation);
		b.setEnabled(true);
		b.setSingleSwf(m_fileInfo.isSwfFilterOn());
		breakpointAdd(b);
		return b;
	}

	/**
	 * Try to resolve any breakpoints which have not yet been resolved.  We
	 * do this every time a new ABC or SWF is loaded.  NOTE: The return
	 * value does NOT indicate whether any breakpoints were resolved!  Rather,
	 * it indicates whether the operation was considered "successful."
	 * If a previously-unresolved breakpoint is now ambiguous, then that is
	 * an error, and the return value is 'false' (indicating that the
	 * debugger should halt).
	 */
	private boolean resolveBreakpoints(StringBuilder sb)
	{
		int count = breakpointCount();
		boolean success = true;
		for (int i=0; i<count; ++i)
		{
			BreakAction b = breakpointAt(i);
			try
			{
				tryResolveBreakpoint(b, sb);
			}
			catch (Exception e) // AmbiguousException or NullPointerException
			{
				Map<String, Object> args = new HashMap<String, Object>();
				args.put("breakpointNumber", Integer.toString(b.getId())); //$NON-NLS-1$
				args.put("expression", b.getBreakpointExpression()); //$NON-NLS-1$
				sb.append(getLocalizationManager().getLocalizedTextString("attemptingToResolve", args)); //$NON-NLS-1$
				sb.append(m_newline);
				sb.append(e.getMessage());
				sb.append(m_newline);
				success = false;
			}
		}
		return success;
	}

	/**
	 * Try to resolve one breakpoint.  We do this every time a new ABC or
	 * SWF is loaded.
	 * @param b the breakpoint to resolve (it's okay if it's already resolved)
	 * @param sb a StringBuilder to which any messages for are appended;
	 * 			to the user.
	 * @return true if the breakpoint is resolved
	 * @throws AmbiguousException
	 * @throws NullPointerException 
	 */
	private boolean tryResolveBreakpoint(BreakAction b, StringBuilder sb) throws AmbiguousException
	{
		int status = b.getStatus();
		boolean resolved = (status == BreakAction.RESOLVED);
		if (status == BreakAction.UNRESOLVED) // we don't do anything for RESOLVED or AMBIGUOUS
		{
			/* wait a bit if we are not halted */
			try
			{
				waitTilHalted(m_activeIsolate);

				// First we check for the case where this breakpoint already has a
				// filename and line number, because those were determined during a
				// previous session, but then the user did a "kill".
				//
				// If this fails, then the "else" clause deals with the case where
				// the user typed in an expression for which we have not yet found
				// a filename and line number.
		    	if (enableBreakpoint(b, b.isAutoDisable(), b.isAutoDelete()))
		    	{
		    		resolved = true;
		    	}
		    	else
		    	{
			        int module = propertyGet(LIST_MODULE);
					int line = propertyGet(LIST_LINE);
					int isolateId = propertyGet(LIST_WORKER);

			        String arg = b.getBreakpointExpression();

			        if (arg != null)
			        {
			            int[] result = parseLocationArg(module, line, arg, isolateId);
		
						// whoo-hoo, it resolved!
		                module = result[0];
		                line = result[1];
		
						// use module SourceFile to denote the name of file in which we wish to set a breakpoint
				        SourceFile f = m_fileInfo.getFile(module, isolateId);
//		                SourceFile f = m_fileInfo.getFakeFile(module);
						LocationCollection col = enableBreak(f, line, isolateId);
						if (col.isEmpty())
							throw new NullPointerException(getLocalizationManager().getLocalizedTextString("noExecutableCode")); //$NON-NLS-1$
						b.setLocations(col);
		
						Location l = col.first();
						SourceFile file = (l != null) ? l.getFile() : null;
						String funcName = (file == null) ? null : file.getFunctionNameForLine(m_session, l.getLine()) ;

						Map<String, Object> args = new HashMap<String, Object>();
						String formatString;
						args.put("breakpointNumber", Integer.toString(b.getId())); //$NON-NLS-1$
						String filename = file.getName();
						if (b.isSingleSwf() && file != null)
						{
							filename = filename + "#" + file.getId(); //$NON-NLS-1$
						}
						args.put("file", filename); //$NON-NLS-1$
						args.put("line", new Integer(l.getLine())); //$NON-NLS-1$

						if (funcName != null)
						{
							args.put("functionName", funcName); //$NON-NLS-1$
							formatString = "resolvedBreakpointToFunction"; //$NON-NLS-1$
						}
						else
						{
							formatString = "resolvedBreakpointToFile"; //$NON-NLS-1$
						}

						sb.append(getLocalizationManager().getLocalizedTextString(formatString, args));
						sb.append(m_newline);
						sb.append(m_newline);
		
						resolved = true;
			        }
		    	}
			}
			catch (NotConnectedException e)
			{
				// Ignore
			}
			catch (NoMatchException e)
			{
				// Okay, it's still not resolved; do nothing
			}
			catch (ParseException e)
			{
				// this shouldn't happen
				if (Trace.error)
					Trace.trace(e.toString());
			}
			catch (AmbiguousException e)
			{
				b.setStatus(BreakAction.AMBIGUOUS);
				throw e; // rethrow
			}
			catch (NullPointerException e)
			{
				b.setStatus(BreakAction.NOCODE);
				throw e; // rethrow
			}
		}
		return resolved;
	}
	
	/**
	 * Enable a breakpoint using the SourceFile as a template
	 * for the source file in which the breakpoint should be 
	 * set.
	 */
	LocationCollection enableBreak(SourceFile f, int line, int isolateId) throws NotConnectedException
	{
        LocationCollection col = new LocationCollection();
		boolean singleSwfBreakpoint = m_fileInfo.isSwfFilterOn();
		SwfInfo swf = m_fileInfo.getSwfFilter();

        // If we have a swf filter enabled then we only want to
        // set a breakpoint in a specific swf not all of them
		try
		{
			if (singleSwfBreakpoint)
			{
				Location l = findAndEnableBreak(swf, f, line);
				col.add(l);
			}
			else
			{
				// walk all swfs looking to add this breakpoint
				SwfInfo[] swfs = m_fileInfo.getSwfs(isolateId);
				for(int i=0; i<swfs.length; i++)
				{
					swf = swfs[i];
					if (swf != null)
					{
						Location l = findAndEnableBreak(swf, f, line);
						if (l != null)
							col.add(l);
					}
				}
			}
		}
		catch(InProgressException ipe)
		{
			if (Trace.error)
				Trace.trace( ( (swf==null)?"SWF ":swf.getUrl() )+" still loading, breakpoint at "+f.getName()+":"+line+" not set"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
		}
		return col;
	}

	/**
	 * Enable a breakpoint for a particular swf if the sourceFile 
	 * is available in that swf.
	 * @param swf if null, then set the breakpoint in the given source file
	 *			otherwise try to locate a matching source file in given swf.
	 * @return null if the swf does not contain this source file
	 */
	Location findAndEnableBreak(SwfInfo swf, SourceFile f, int line) throws NotConnectedException, InProgressException
	{
		int fileId = f.getId();
		if (swf != null)
		{
			SourceFile sameFile = m_fileInfo.similarFileInSwf(swf, f);
			if (sameFile != null)
				fileId = sameFile.getId();
			else 
				fileId = -1;
		}

		Location l = (fileId > -1) ? breakEnableRequest(fileId, line, swf.getIsolateId()) : null;
		return l;
	}

	/**
	 * Received when a breakpoint has been removed (or disabled)
	 */
	Location breakEnableRequest(int fileId, int line, int isolateId) throws NotConnectedException
	{
		Location l = null;
		try
		{
			l = m_session.getWorkerSession(isolateId).setBreakpoint(fileId, line);
		}
		catch(NoResponseException nre)
		{
			/**
			 * This could be that we have an old player which does not
			 * respond to this request, or that we have a new player and
			 * the location was not set.
			 */
		}
		return l;
	}

	/**
	 * Notification that a breakpoint has been removed (or disabled)
	 * at the CLI level and we may need to remove it at the session level
	 */
	void breakDisableRequest(LocationCollection col) throws NotConnectedException
	{
		// now let's comb the table looking to see if this breakpoint should
		// be removed at the session level.  Use the first entry as a template
		// for which location we are talking about.
		int at = 0;
		boolean hit = false;
		Location l = col.first();
		do
		{
		    at = breakpointIndexOf(l, at);
			if (at > -1)
			{
				if (breakpointAt(at).isEnabled())
					hit = true;
				else
					at++; // our location match is not enabled but let's continue after the hit
			}
		}
		while(at > -1 && !hit);

		// no one matches, so let's remove it at the session level
		if (!hit)
		{
			Iterator<Location> itr = col.iterator();
			while(itr.hasNext())
			{
				l = itr.next();
				try { m_session.clearBreakpoint(l); } catch(NoResponseException nre) {}
			}
		}
	}

	BreakAction breakpointAt(int at) {
//		if (isolateId == Isolate.DEFAULT_ID)
			return m_breakpoints.elementAt(at);
//		else
//			return getIsolateState(isolateId).m_breakpoints.elementAt(at);
	}

	boolean breakpointAdd(BreakAction a) {
//		if (isolateId == Isolate.DEFAULT_ID)
			return m_breakpoints.add(a);
//		else
//			return getIsolateState(isolateId).m_breakpoints.add(a);
		
	}

	int breakpointCount() {
//		if (isolateId == Isolate.DEFAULT_ID)
			return m_breakpoints.size();
//		else
//			return getIsolateState(isolateId).m_breakpoints.size();
	}

	/**
	 * Probe the table looking for the first breakpoint that
	 * matches our criteria.  Various permutations of the call are supported.
	 */
	int breakpointIndexOf(int fileId, int line) {
		return breakpointIndexOf(fileId, line, 0, true);
	}

	int breakpointIndexOf(Location l, int start) {
		return breakpointIndexOf(l.getFile().getId(), l.getLine(), start, true);
	}

	int enabledBreakpointIndexOf(Location l) {
		return breakpointIndexOf(l.getFile().getId(), l.getLine(), 0, false);
	}

	int breakpointIndexOf(int fileId, int line, int start, boolean includeDisabled)
	{
		int size = breakpointCount();
		int hit = -1;
		for(int i=start; (hit<0) && (i<size) ; i++)
		{
			BreakAction b = breakpointAt(i);
			if (b.locationMatches(fileId, line) && (includeDisabled || b.isEnabled()) )
				hit = i;
		}
		return hit;
	}

	// probe by identifier
	int breakpointIndexOf(int id)
	{
		int size = breakpointCount();
		int hit = -1;

		for(int i=0; (hit<0) && (i<size) ; i++)
		{
			BreakAction b = breakpointAt(i);
			if (b.getId() == id)
				hit = i;
		}
		return hit;
	}

	// access to display
	DisplayAction		displayAt(int at)				{ return m_displays.get(at); 	}
	boolean				displayAdd(DisplayAction a)		{ return m_displays.add(a); 	}
	void				displayRemoveAt(int at)			{ m_displays.remove(at); 	}
	int					displayCount()					{ return m_displays.size(); 	}

	// probe by id
	int displayIndexOf(int id)
	{
		int size = displayCount();
		int hit = -1;

		for(int i=0; (hit<0) && (i<size) ; i++)
		{
			DisplayAction b = displayAt(i);
			if (b.getId() == id)
				hit = i;
		}
		return hit;
	}

	void doSet() throws NotConnectedException
	{
		/* wait a bit if we are not halted */
//		waitTilHalted();
		try
		{
			ValueExp exp = null;

			if (!hasMoreTokens())
				err(getLocalizationManager().getLocalizedTextString("setCommand")); //$NON-NLS-1$
			else
			{
				// pull the expression
				String s = restOfLine();

				// parse and eval which causes the assignment to occur...
				if ( (exp = parseExpression(s)) == null )
					;  // failed parse

				// make sure contains assignment

				else if ( !exp.containsAssignment() )
					throw new IllegalAccessException("="); //$NON-NLS-1$

				else
					evalExpression(exp, m_activeIsolate);
			}
		}
		catch(IllegalAccessException iae)
		{
			Map<String, Object> args = new HashMap<String, Object>();
			args.put("operator", iae.getMessage()); //$NON-NLS-1$
			err(getLocalizationManager().getLocalizedTextString("missingOperator", args)); //$NON-NLS-1$
		}
		catch(NullPointerException npe)
		{
			err(getLocalizationManager().getLocalizedTextString("couldNotEvaluate")); //$NON-NLS-1$
		}
	}

	void doPrint() throws NotConnectedException
	{
		/* wait a bit if we are not halted */
//		waitTilHalted();
		try
		{
			Object result = null;
			boolean isLookupMembers = false;

			if (!hasMoreTokens())
			{
				try
				{
					// attempt to get the last result
					result = m_exprCache.get("$"); //$NON-NLS-1$
				}
				catch(ArrayIndexOutOfBoundsException aib)
				{
					err(getLocalizationManager().getLocalizedTextString("commandHistoryIsEmpty")); //$NON-NLS-1$
					throw new NullPointerException();
				}
			}
			else
			{
				// pull the rest of the line
				String s = restOfLine();

				// first parse it, then attempt to evaluate the expression
				ValueExp expr = parseExpression(s);

				// make sure no assignment
				if ( expr.containsAssignment() )
					throw new IllegalAccessException();

				result = evalExpression(expr, m_activeIsolate).value;
				isLookupMembers = expr.isLookupMembers();
			}

			/* it worked, add it to the list */
			int which = m_exprCache.add(result);

			/* dump the output */
			StringBuilder sb = new StringBuilder();
			sb.append('$');
			sb.append(which);
			sb.append(" = "); //$NON-NLS-1$

			if (result instanceof Variable)
				result = ((Variable)result).getValue();

			if (result instanceof InternalProperty)
				sb.append( ((InternalProperty)result).valueOf() );
			else if (isLookupMembers)
				sb.append(result);
			else
				ExpressionCache.appendVariableValue(sb, result, m_activeIsolate);

			out( sb.toString() );

			m_repeatLine = m_currentLine;
		}
		catch(ArrayIndexOutOfBoundsException aio)
		{
			// $n not in range 0..size
			Map<String, Object> args = new HashMap<String, Object>();
			args.put("number", aio.getMessage()); //$NON-NLS-1$
			err(getLocalizationManager().getLocalizedTextString("historyHasNotReached", args)); //$NON-NLS-1$
		}
		catch(IllegalAccessException iae)
		{
			err(getLocalizationManager().getLocalizedTextString("noSideEffectsAllowed")); //$NON-NLS-1$
		}
		catch(NoSuchVariableException nsv)
		{
			Map<String, Object> args = new HashMap<String, Object>();
			args.put("variable", nsv.getMessage()); //$NON-NLS-1$
			err(getLocalizationManager().getLocalizedTextString("variableUnknown", args)); //$NON-NLS-1$
		}
		catch(NullPointerException npe)
		{
			err(getLocalizationManager().getLocalizedTextString("couldNotEvaluate")); //$NON-NLS-1$
		}
	}

	/* parse the given string and produce an error message as appropriate */
	ValueExp parseExpression(String s)
	{
		ValueExp expr = null;
		try
		{
			expr = m_exprCache.parse(s);
		}
		catch(ParseException pe)
		{
			// bad operation code
			err(getLocalizationManager().getLocalizedTextString("expressionCouldNotBeParsed") + " " + pe.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
		}
		catch(IOException io)
		{
			// thrown from parser
			err(getLocalizationManager().getLocalizedTextString("expressionCouldNotBeParsed") + " " + s); //$NON-NLS-1$ //$NON-NLS-2$
		}
		return expr;
	}

	/*
	 * Evaluate the given expression
	 */
	EvaluationResult evalExpression(ValueExp expr, int isolateId) { return evalExpression(expr, true, isolateId); }

	EvaluationResult evalExpression(ValueExp expr, boolean displayExceptions, int isolateId)
	{
		/* now we go off and evaluate the expression */
		EvaluationResult result = null;
		try
		{
			result = m_exprCache.evaluate(expr, isolateId);
		}
		catch(NoSuchVariableException nsv)
		{
			if (displayExceptions)
			{
				Map<String, Object> args = new HashMap<String, Object>();
				args.put("variable", nsv.getMessage()); //$NON-NLS-1$
				err(getLocalizationManager().getLocalizedTextString("variableUnknown", args)); //$NON-NLS-1$
			}
		}
		catch(NumberFormatException nfe)
		{
			if (displayExceptions)
			{
				Map<String, Object> args = new HashMap<String, Object>();
				args.put("value", nfe.getMessage()); //$NON-NLS-1$
				err(getLocalizationManager().getLocalizedTextString("couldNotConvertToNumber", args)); //$NON-NLS-1$
			}
		}
		catch(PlayerFaultException pfe)
		{
			if (displayExceptions)
				err(pfe.getMessage());
		}
		catch (PlayerDebugException e)
		{
			if (displayExceptions)
				err(e.getMessage());
		}

		return result;
	}

	/**
	 * Specialized dump of the contents of a movie clip tree, dumping
	 * all the _target properties of all MCs
	 * @throws NoResponseException 
	 * @throws NotSuspendedException 
	 */
	void doMcTree() throws NotConnectedException, NotSuspendedException, NoResponseException
	{
		/* wait a bit if we are not halted */
		waitTilHalted(m_activeIsolate);
		try
		{
			String var = nextToken();  // our variable reference
			String member = "_target"; //$NON-NLS-1$
			boolean printPath = false;
			Object result = null;
			String name = null;

			// did the user specify a member name
			if (hasMoreTokens())
			{
				member = nextToken();

				// did they specify some other options
				while(hasMoreTokens())
				{
					String option = nextToken();
					if (option.equalsIgnoreCase("fullpath")) //$NON-NLS-1$
						printPath = true;
				}
			}

			// first parse it, then attempt to evaluate the expression
			ValueExp expr = parseExpression(var);
			result = evalExpression(expr, m_activeIsolate).value;

			StringBuilder sb = new StringBuilder();

			if (result instanceof Variable)
			{
				name = ((Variable)result).getName();
				result = ((Variable)result).getValue();
			}

			// It worked an should now be a value that we can traverse looking for member properties

			if (result instanceof Value)
			{
				ArrayList<Object> e = new ArrayList<Object>();
				dumpTree(new HashMap<Object, String>(), e, name, (Value)result, member);

				// now sort according to our criteria
				treeResults(sb, e, member, printPath);
			}
			else
				throw new NoSuchVariableException(result);

			out( sb.toString() );
		}
		catch(NoSuchVariableException nsv)
		{
			Map<String, Object> args = new HashMap<String, Object>();
			args.put("variable", nsv.getMessage()); //$NON-NLS-1$
			err(getLocalizationManager().getLocalizedTextString("variableUnknown", args)); //$NON-NLS-1$
		}
		catch(NullPointerException npe)
		{
			err(getLocalizationManager().getLocalizedTextString("couldNotEvaluate")); //$NON-NLS-1$
		}
	}

	/**
	 * Set the context from which info files
	 * and all other file releated commands
	 * will operate from.
	 *
	 * It no swf is given then we use the
	 * default mode which is to display all
	 * files from all swfs.  Files with identical
	 * names are only displayed once.
	 */
	void doViewSwf()
	{
		try
		{
			if (hasMoreTokens())
			{
				String swfName = nextToken();
				Map<String, Object> args = new HashMap<String, Object>();
				args.put("swf", swfName); //$NON-NLS-1$
				if (m_fileInfo.setSwfFilter(swfName))
				{
					out(getLocalizationManager().getLocalizedTextString("commandsLimitedToSpecifiedSwf", args)); //$NON-NLS-1$
				}
				else
				{
					err(getLocalizationManager().getLocalizedTextString("notValidSwf", args)); //$NON-NLS-1$
				}
			}
			else
			{
				m_fileInfo.setSwfFilter(null);
				out(getLocalizationManager().getLocalizedTextString("commandsApplyToAllSwfs")); //$NON-NLS-1$
			}
		}
		catch(NullPointerException npe)
		{
			err(getLocalizationManager().getLocalizedTextString("noActiveSession")); //$NON-NLS-1$
		}
	}

	/**
	 * Increment the frame context by 1 and display the new current frame.
	 */
	void doUp() throws PlayerDebugException
	{
		int num = propertyGet(DISPLAY_FRAME_NUMBER) + 1;
		try
		{
			propertyPut(DISPLAY_FRAME_NUMBER, num);

			dumpFrame(num);
			setListingToFrame(num);
		}
		catch(NullPointerException npe)
		{
			err(getLocalizationManager().getLocalizedTextString("noActiveSession")); //$NON-NLS-1$
		}
        catch(ArrayIndexOutOfBoundsException aie)
        {
        	Map<String, Object> args = new HashMap<String, Object>();
        	args.put("frameNumber", Integer.toString(num)); //$NON-NLS-1$
            err(getLocalizationManager().getLocalizedTextString("frameDoesNotExist", args)); //$NON-NLS-1$
        }
		m_repeatLine = m_currentLine;
	}

	/**
	 * Decrement the frame context by 1 and display the new current frame.
	 */
	void doDown() throws PlayerDebugException
	{
		int num = propertyGet(DISPLAY_FRAME_NUMBER) - 1;
		try
		{
			propertyPut(DISPLAY_FRAME_NUMBER, num);

			dumpFrame(num);
			setListingToFrame(num);
		}
		catch(NullPointerException npe)
		{
			err(getLocalizationManager().getLocalizedTextString("noActiveSession")); //$NON-NLS-1$
		}
        catch(ArrayIndexOutOfBoundsException aie)
        {
        	Map<String, Object> args = new HashMap<String, Object>();
        	args.put("frameNumber", Integer.toString(num)); //$NON-NLS-1$
            err(getLocalizationManager().getLocalizedTextString("frameDoesNotExist", args)); //$NON-NLS-1$
        }
		m_repeatLine = m_currentLine;
	}

	/**
	 * Set the frame context to the given number and display the new current frame.
	 */
	void doFrame() throws PlayerDebugException
	{
		int num = 0;  // frame 0 by default 
		try
		{
			if (hasMoreTokens())
				num = nextIntToken();

			propertyPut(DISPLAY_FRAME_NUMBER, num);

			dumpFrame(num);
			setListingToFrame(num);
		}
		catch(NumberFormatException nfe)
		{
			Map<String, Object> args = new HashMap<String, Object>();
			args.put("token", m_currentToken); //$NON-NLS-1$
			err(getLocalizationManager().getLocalizedTextString("notANumber", args)); //$NON-NLS-1$
		}
        catch(ArrayIndexOutOfBoundsException aie)
        {
        	Map<String, Object> args = new HashMap<String, Object>();
        	args.put("frameNumber", Integer.toString(num)); //$NON-NLS-1$
            err(getLocalizationManager().getLocalizedTextString("frameDoesNotExist", args)); //$NON-NLS-1$
        }
		catch(NullPointerException npe)
		{
			err(getLocalizationManager().getLocalizedTextString("noActiveSession")); //$NON-NLS-1$
		}
	}

	// Displays information on the current frame
    // @throws ArrayIndexOutOfBoundsException if frame 'frm' doesn't exist
	void dumpFrame(int frm) throws PlayerDebugException, ArrayIndexOutOfBoundsException
	{
		StringBuilder sb = new StringBuilder();
		Frame[] ar = m_session.getFrames();
		appendFrameInfo(sb, ar[frm], frm, false, true);

		sb.append(m_newline);
		out(sb.toString());
	}

	// set the listing command to point to the file/line of the given frame
	void setListingToFrame(int frameNum) throws PlayerDebugException
	{
		// set the module and line
		Frame[] frames = m_session.getFrames();
		Frame ctx = frames[frameNum];

		Location l = ctx.getLocation();
		SourceFile f = l.getFile();
		int id = f.getId();
		int line = l.getLine();

        setListingPosition(id, line, ctx.getIsolateId());
    }

    // Set teh listing position to change to the given module and line number
    // also triggers emacs to move to this position if enabled
    void setListingPosition(int module, int line, int workerid)
    {
		propertyPut(LIST_MODULE, module);
		propertyPut(LIST_LINE, line);
		propertyPut(LIST_WORKER, workerid);

        // if we are running under emacs then dump out our new location
        if (m_fullnameOption)
        {
            SourceFile f = m_fileInfo.getFile(module);
            if (f != null)
            {
                StringBuilder sb = new StringBuilder();
                appendFullnamePosition(sb, f, line);
                sb.append('\n'); // not sure why this is needed but it seems to address some emacs bugs
                out(sb.toString());
            }
        }
	}

	/**
	 * Traverse the given variables dumping any Movieclips we find that
	 * contain a member called 'member'
	 * @throws NotConnectedException 
	 * @throws NoResponseException 
	 * @throws NotSuspendedException 
	 */
	void dumpTree(Map<Object, String> tree, List<Object> e, String name, Value result, String member) throws NotSuspendedException, NoResponseException, NotConnectedException
	{
		// name for this variable
		if (name == null)
			name = ""; //$NON-NLS-1$

		// have we seen it already
		if (tree.containsKey(result))
			return;

		tree.put(result, name);  // place it

		// first iterate over our members looking for 'member'
		Value proto = result;
		boolean done = false;
		while(!done && proto != null)
		{
			Variable[] members = proto.getMembers(m_session);
			proto = null;

			// see if we find one called 'member'
			for(int i=0; i<members.length; i++)
			{
				Variable m = members[i];
				String memName = m.getName();
				if (memName.equals(member) && !tree.containsKey(m))
				{
					e.add(name);
					e.add(result);
					e.add(m);
					tree.put(m, name+"."+memName); //$NON-NLS-1$
					done = true;
				}
				else if (memName.equals("__proto__")) //$NON-NLS-1$
					proto = members[i].getValue();
			}
		}

		// now traverse other mcs recursively
		done = false;
		proto = result;
		while(!done && proto != null)
		{
			Variable[] members = proto.getMembers(m_session);
			proto = null;

			// see if we find an mc
			for(int i=0; i<members.length; i++)
			{
				Variable m = members[i];
				String memName = m.getName();

				// if our type is NOT object or movieclip then we are done
				if (m.getValue().getType() != VariableType.OBJECT && m.getValue().getType() != VariableType.MOVIECLIP)
					;
				else if (m.getValue().getId() != Value.UNKNOWN_ID)
					dumpTree(tree, e, name, m.getValue(), member);
				else if (memName.equals("__proto__")) //$NON-NLS-1$
				{
					proto = m.getValue();
//					name = name + ".__proto__";
				}
			}
		}
	}

	StringBuilder treeResults(StringBuilder sb, List<Object> e, String memName, boolean fullName)
	{
		// walk the list
		Iterator<Object> i = e.iterator();
		while(i.hasNext())
		{
			String name = (String) i.next();
			Variable key = (Variable) i.next();
			Variable val = (Variable)i.next();

//			sb.append(key);
//			sb.append(".");
//			sb.append(val.getName());
			if (fullName)
				sb.append(name);
			ExpressionCache.appendVariableValue(sb, key.getValue(), key.getName(), key.getIsolateId());
			sb.append("."); //$NON-NLS-1$
			sb.append(memName);
			sb.append(" = "); //$NON-NLS-1$
			ExpressionCache.appendVariableValue(sb, val.getValue(), val.getName(), val.getIsolateId());
			sb.append(m_newline);
		}
		return sb;
	}

	/**
	 * Output a source line of code to the output channel formatting nicely
	 */
	public void outputSource(int module, int line, String s)
	{
		StringBuilder sb = new StringBuilder();
		appendSource(sb, module, line, s, true);
		out( sb.toString() );
	}

	void appendSource(StringBuilder sb, int module, int line, String s, boolean markCurrent)
	{
		String lineS = String.valueOf(line);
		int padding = 6 - lineS.length();

		// if we are the current location then mark it
		if (markCurrent && isCurrentLocation(module, line))
			sb.append('=');
		else
			sb.append(' ');
		sb.append(lineS);
		repeat(sb, ' ', padding);
		sb.append(s);
	}

	// see if this module, line combo is the current location
	boolean isCurrentLocation(int module, int line)
	{
		boolean yes = false;
		Location l = getCurrentLocation();
		if (l != null)
		{
			SourceFile file = l.getFile();
			if (file != null && file.getId() == module && l.getLine() == line)
				yes = true;
		}
		return yes;
	}

    private int parseLineNumber(String lineNumber) throws ParseException
    {
        try
        {
            return Integer.parseInt(lineNumber);
        }
        catch(NumberFormatException nfe)
        {
        	Map<String, Object> args = new HashMap<String, Object>();
        	args.put("token", lineNumber); //$NON-NLS-1$
        	throw new ParseException(getLocalizationManager().getLocalizedTextString("expectedLineNumber", args), 0); //$NON-NLS-1$
        }
    }

    private int parseFileNumber(String fileNumber) throws ParseException
    {
        try
        {
            return Integer.parseInt(fileNumber);
        }
        catch(NumberFormatException nfe)
        {
        	Map<String, Object> args = new HashMap<String, Object>();
        	args.put("token", fileNumber); //$NON-NLS-1$
        	throw new ParseException(getLocalizationManager().getLocalizedTextString("expectedFileNumber", args), 0); //$NON-NLS-1$
        }
    }

    private int parseFileName(String partialFileName) throws NoMatchException, AmbiguousException
    {
        SourceFile[] sourceFiles = m_fileInfo.getFiles(partialFileName);
        int nSourceFiles = sourceFiles.length;

        if (nSourceFiles == 0)
        {
        	Map<String, Object> args = new HashMap<String, Object>();
        	args.put("name", partialFileName); //$NON-NLS-1$
            throw new NoMatchException(getLocalizationManager().getLocalizedTextString("noSourceFileWithSpecifiedName", args)); //$NON-NLS-1$
        }

        else if (nSourceFiles > 1)
        {
            String s = getLocalizationManager().getLocalizedTextString("ambiguousMatchingFilenames") + m_newline; //$NON-NLS-1$
            for (int i = 0; i < nSourceFiles; i++)
            {
                SourceFile sourceFile = sourceFiles[i];
                s += " " + sourceFile.getName() + "#" + sourceFile.getId(); //$NON-NLS-1$ //$NON-NLS-2$
                if (i < nSourceFiles - 1)
                    s += m_newline;
            }
            throw new AmbiguousException(s);
        }
        return sourceFiles[0].getId();
    }

	/* used by parseFunctionName */
	private static class ModuleFunctionPair implements Comparable<ModuleFunctionPair>
	{
		public ModuleFunctionPair(int moduleId, String functionName) {
			this.moduleId = moduleId;
			this.functionName = functionName;
		}
		public int moduleId;
		public String functionName;

		public int compareTo(ModuleFunctionPair other) {
			return functionName.compareTo(other.functionName);
		}
	}

	/**
	 * Parse a partial function name
	 * @param module the FIRST module to search; but we also search all the others if 'onlyThisModule' is false
	 * @return two ints: first is the module, and second is the line
	 */
    private int[] parseFunctionName(int module, String partialFunctionName, boolean onlyThisModule) throws NoMatchException, AmbiguousException
    {
        try { waitForMetaData(); } catch(InProgressException ipe) {}  // wait a bit before we try this to give the background thread time to complete

        SourceFile m = m_fileInfo.getFile(module, m_activeIsolate);
		ArrayList<ModuleFunctionPair> functionNames = new ArrayList<ModuleFunctionPair>(); // each member is a ModuleFunctionPair

        appendFunctionNamesMatching(functionNames, m, partialFunctionName);

        if (functionNames.size() == 0)
        {
			if (!onlyThisModule)
			{
				// not found in the specified module; search all the other modules
				for (Isolate isolate : m_session.getWorkers()) {
					Iterator fileIter = m_fileInfo.getAllFiles(isolate.getId());
					while (fileIter.hasNext())
					{
						SourceFile nextFile = (SourceFile) ((Map.Entry)fileIter.next()).getValue();
						if (nextFile != m) // skip the one file we searched at the beginning
						{
							appendFunctionNamesMatching(functionNames, nextFile, partialFunctionName);
						}
					}
				}
			}

			if (functionNames.size() == 0)
			{
	        	Map<String, Object> args = new HashMap<String, Object>();
	        	args.put("name", partialFunctionName); //$NON-NLS-1$
	            throw new NoMatchException(getLocalizationManager().getLocalizedTextString("noFunctionWithSpecifiedName", args)); //$NON-NLS-1$
			}
        }

		if (functionNames.size() > 1)
        {
			ModuleFunctionPair[] functionNameArray = functionNames.toArray( new ModuleFunctionPair[functionNames.size()] );
			Arrays.sort(functionNameArray);

            String s = getLocalizationManager().getLocalizedTextString("ambiguousMatchingFunctionNames") + m_newline; //$NON-NLS-1$
            Map<String, Object> args = new HashMap<String, Object>();
            for (int i = 0; i < functionNameArray.length; i++)
            {
				//String moduleName = m_fileInfo.getFile(functionNameArray[i].moduleId).getName();
            	String moduleName = m_fileInfo.getFile(functionNameArray[i].moduleId, m_activeIsolate).getName();
                String functionName = functionNameArray[i].functionName;
                args.put("functionName", functionName); //$NON-NLS-1$
                args.put("filename", moduleName + "#" + functionNameArray[i].moduleId); //$NON-NLS-1$ //$NON-NLS-2$
                s += " " + getLocalizationManager().getLocalizedTextString("functionInFile", args); //$NON-NLS-1$ //$NON-NLS-2$
                if (i < functionNameArray.length - 1)
                    s += m_newline;
            }
            throw new AmbiguousException(s);
        }

		ModuleFunctionPair pair = functionNames.get(0);
		module = pair.moduleId;
		m = m_fileInfo.getFile(module, m_activeIsolate);
		int line = m.getLineForFunctionName(m_session, pair.functionName);
        return new int[] { module, line };
     }

    /**
     * Find function names in this module that start with
     * the specified string, and append them to the specified List.
	 *
	 * If partialName contains parenthesis then we look for an exact match
     */
	private void appendFunctionNamesMatching(List<ModuleFunctionPair> functionNameList, SourceFile m, String partialName)
	{
		int exactHitAt = -1;

		// trim off the trailing parenthesis, if any
		int parenAt = partialName.lastIndexOf('(');
		if (parenAt > -1)
			partialName = partialName.substring(0, parenAt);

		String[] names = m.getFunctionNames(m_session);
		for(int i=0; i<names.length; i++)
        {
            String functionName = names[i];
            if (functionName.equals(partialName))
			{
				exactHitAt = i;
				break;
			}
			else if (functionName.startsWith(partialName))
                functionNameList.add(new ModuleFunctionPair(m.getId(), functionName));
        }

		// exact match?
		if (exactHitAt > -1)
		{
			functionNameList.clear();
			functionNameList.add(new ModuleFunctionPair(m.getId(), names[exactHitAt]));
		}
	}


    /**
      * Parse arg to determine which file it specifies.
      * Allowed formats: #29, MyApp.mxml, MyA
      * A variety of exceptions are thrown for other formats.
      */
    public int parseFileArg(int module, String arg) throws ParseException, AmbiguousException, NoMatchException
    {
        /* Special case: a location arg like :15 produces a file arg
           which is an empty string. */
        if (arg.length() == 0)
            return module;

        char firstChar = arg.charAt(0);

        /* The first character can't be 0-9 or '-'. */
        if (Character.isDigit(firstChar) || firstChar == '-')
        {
        	Map<String, Object> args = new HashMap<String, Object>();
        	args.put("token", arg); //$NON-NLS-1$
        	throw new ParseException(getLocalizationManager().getLocalizedTextString("expectedFile", args), 0); //$NON-NLS-1$
        }
        /* If the first character is '#', the rest must be a file number. */
        else if (firstChar == '#')
        {
            return parseFileNumber(arg.substring(1));
        }
        /* Otherwise, assume beforeColon is a full or partial file name. */
        else
        {
            return parseFileName(arg);
        }
    }

    /**
      * Parse arg to determine which line it specifies.
      * Allowed formats: 17, MyFunction, MyF
      * A variety of exceptions are thrown for other formats.
      */
    public int parseLineArg(int module, String arg) throws ParseException, AmbiguousException, NoMatchException
    {
        /* Special case: a location arg like #29: produces a line arg
           which is an empty string. */
         if (arg.length() == 0)
            return 1;

        char firstChar = arg.charAt(0);

        /* If the first character is 0-9 or '-', arg is assumed to be a line number. */
        if (Character.isDigit(firstChar) || firstChar == '-')
        {
            return parseLineNumber(arg);
        }
        /* The first character can't be '#'. */
        else if (firstChar == '#')
        {
        	Map<String, Object> args = new HashMap<String, Object>();
        	args.put("token", arg); //$NON-NLS-1$
        	throw new ParseException(getLocalizationManager().getLocalizedTextString("expectedLineNumber", args), 0); //$NON-NLS-1$
        }
        /* Otherwise, assume arg is a full or partial function name. */
        else
        {
            int[] moduleAndLine = parseFunctionName(module, arg, true);
			return moduleAndLine[1];
        }
    }

    /**
     * Parse arg to figure out what module and line it specifies.
     *
     * Allowed formats (assuming Button.as is file #29
     * and the first line of MyFunction is line 17):
     *
     *  arg                     module      line
     *  17                      no change   17
     *  MyFunction              no change   17
     *  MyF                     no change   17
     *  #29                     29          1
     *  Button.as               29          1
     *  Bu                      29          1
     *  #29:17                  29          17
     *  #29:MyFunction          29          17
     *  #29:MyF                 29          17
     *  Button.as:17            29          17
     *  Button.as:MyFunction    29          17
     *  Button.as:MyF           29          17
     *  Bu:17                   29          17
     *  Bu:MyFunction           29          17
     *  Bu:MyF                  29          17
     *
     * A variety of exceptions are thrown for other formats.
     */
    public int[] parseLocationArg(int module, int line, String arg, int isolateId) throws ParseException, AmbiguousException, NoMatchException
    {
        int colonAt = arg.indexOf(':');
		int wasFunc = 0;  // set to 1 if a function was named

        /* First deal with the case where arg doesn't contain a ':'
           and therefore might be specifying either a file or a line. */
        if (colonAt < 0)
        {
            char firstChar = arg.charAt(0);

            /* If the first character is 0-9 or '-', arg is assumed to be a line number. */
            if (Character.isDigit(firstChar) || firstChar == '-')
            {
                line = parseLineNumber(arg);
            }
            /* If the first character is a '#', what follows
               is assumed to be a file number. */
            else if (firstChar == '#')
            {
                module = parseFileNumber(arg.substring(1));
                line = 1;
            }
            /* Otherwise, assume arg is a full or partial function name or file name. */
            else
            {
                /* Assume arg is a full or partial function in the specified module. */
                try
                {
                    int[] moduleAndLine = parseFunctionName(module, arg, false);
					module = moduleAndLine[0];
					line = moduleAndLine[1];
					wasFunc = 1;
                }
                /* If it isn't, assume arg is a full or partial file name. */
                catch(NoMatchException pe)
                {
					try
					{
						module = parseFileName(arg);
						line = 1;
					}
					catch(NoMatchException pee)
					{
						// catch the 'file name' string
						Map<String, Object> args = new HashMap<String, Object>();
						args.put("token", arg); //$NON-NLS-1$
						throw new NoMatchException(getLocalizationManager().getLocalizedTextString("noSuchFileOrFunction", args)); //$NON-NLS-1$
					}
                }
            }
        }

        /* Now deal with the case where arg contains a ':',
           and is therefore specifying both a file and a line. */
        else
        {
            module = parseFileArg(module, arg.substring(0, colonAt));
            line = parseLineArg(module, arg.substring(colonAt + 1));
			wasFunc = (arg.substring(colonAt+1).length() > 1 && Character.isDigit(arg.substring(colonAt+1).charAt(0)) ) ? 0 : 1;
        }

        return new int[] { module, line, wasFunc };
    }

	/**
	 * Print the context of a Variable
	 */
	void doWhat() throws NotConnectedException
	{
		/* wait a bit if we are not halted */
		waitTilHalted(m_activeIsolate);
		try
		{
			Object result = null;

			/* pull the rest of the line */
			String s = restOfLine();

			// first parse it, then attempt to evaluate the expression
			ValueExp expr = parseExpression(s);

			// make sure no assignment
			if ( expr.containsAssignment() )
				throw new IllegalAccessException();

			result = evalExpression(expr, m_activeIsolate).value;

			/* dump the output */
			StringBuilder sb = new StringBuilder();

			if (result instanceof Variable)
			{
				Variable v = (Variable) result;

				// if it has a path then display it!
				if (v.isAttributeSet(VariableAttribute.IS_LOCAL))
					s = getLocalizationManager().getLocalizedTextString("localVariable"); //$NON-NLS-1$
				else if (v.isAttributeSet(VariableAttribute.IS_ARGUMENT))
					s = getLocalizationManager().getLocalizedTextString("functionArgumentVariable"); //$NON-NLS-1$
				else if ( (v instanceof VariableFacade) && (s = ((VariableFacade)v).getPath()) != null && s.length() > 0 )
					;
				else
					s = "_global"; //$NON-NLS-1$

				sb.append(s);
			}
			else
				sb.append(getLocalizationManager().getLocalizedTextString("mustBeOnlyOneVariable")); //$NON-NLS-1$

			out( sb.toString() );
		}
		catch(IllegalAccessException iae)
		{
			err(getLocalizationManager().getLocalizedTextString("noSideEffectsAllowed")); //$NON-NLS-1$
		}
		catch(NullPointerException npe)
		{
			err(getLocalizationManager().getLocalizedTextString("couldNotEvaluate")); //$NON-NLS-1$
		}
	}

    /*
     * We accept zero, one or two args for this command. Zero args
     * means list the next 10 line around the previous listing.  One argument
     * specifies a line and 10 lines are listed around that line.  Two arguments
     * with a command between specifies starting and ending lines.
     */
	void doList()
	{
        /* currentXXX may NOT be invalid! */

		int currentModule = propertyGet(LIST_MODULE);
        int currentLine = propertyGet(LIST_LINE);
        int listsize = propertyGet(LIST_SIZE);
        int workerid = propertyGet(LIST_WORKER);

        String arg1 = null;
        int module1 = currentModule;
        int line1 = currentLine;

        String arg2 = null;
        int line2 = currentLine;

        int numLines = 0;

		try
		{
            if (hasMoreTokens())
			{
                arg1 = nextToken();

                if (arg1.equals("-")) //$NON-NLS-1$
                {
					// move back two times the listing size and if listsize is odd then move forward one
                    line1 = line2 = line1 - (2 * listsize);
                }
                else
                {
                    int[] result = parseLocationArg(currentModule, currentLine, arg1, workerid);
                    module1 = result[0];
                    line2 = line1 = result[1];

                    if (hasMoreTokens())
                    {
                        arg2 = nextToken();
                        line2 = parseLineArg(module1, arg2);
                    }
                }
			}

//			System.out.println("1="+module1+":"+line1+",2=:"+line2);

			/**
			 * Check for a few error conditions, otherwise we'll write a listing!
			 */
			if (hasMoreTokens())
			{
				err(getLocalizationManager().getLocalizedTextString("lineJunk")); //$NON-NLS-1$
			}
			else
			{
				int half = listsize/2;
				SourceFile file = m_fileInfo.getFile(module1, workerid);
//				SourceFile file = m_fileInfo.getFakeFile(module1);
				numLines = file.getLineCount();

				int newLine;
				if (numLines == 1 && file.getLine(1).equals("")) //$NON-NLS-1$
				{
					// there's no source in the file at all!
					// this presumably means that the source file isn't in the current directory
					err(getLocalizationManager().getLocalizedTextString("sourceFileNotFound")); //$NON-NLS-1$
					newLine = currentLine;
				}
				else
				{
					// pressing return is ok, otherwise throw the exception
					if (line1 > numLines && arg1 != null)
						throw new IndexOutOfBoundsException();
	
					/* if no arg2 then user requested the next N lines around something */
					if (arg2 == null)
					{
						line2 = line1 + (half) - 1;
						line1 = line1 - (listsize-half);
					}

					/* adjust our range of lines to ensure we conform */
					if (line1 < 1)
					{
						/* shrink line 1, grow line2 */
						line2 += -(line1 - 1);
						line1 = 1;
					}
	
					if (line2 > numLines)
						line2 = numLines;
	
//				    System.out.println("1="+module1+":"+line1+",2="+module2+":"+line2+",num="+numLines+",half="+half);
	
					/* nothing to display */
					if (line1 > line2)
						throw new IndexOutOfBoundsException();
	
					/* now do it! */
					SourceFile source = m_fileInfo.getFile(module1, workerid);
					for(int i=line1; i<=line2; i++)
						outputSource(module1, i, source.getLine(i));
					
					newLine = line2 + half + (((listsize % 2) == 0) ? 1 : 2);  // add one if even, 2 for odd;
				}
				
				/* save away valid context */
				propertyPut(LIST_MODULE, module1);
				propertyPut(LIST_LINE, newLine);
				propertyPut(LIST_WORKER, workerid);
				m_repeatLine = "list";   /* allow repeated listing by typing CR */ //$NON-NLS-1$
			}
		}
        catch(IndexOutOfBoundsException iob)
		{
			String name = "#"+module1; //$NON-NLS-1$
			Map<String, Object> args = new HashMap<String, Object>();
			args.put("line", Integer.toString(line1)); //$NON-NLS-1$
			args.put("filename", name); //$NON-NLS-1$
			args.put("total", Integer.toString(numLines)); //$NON-NLS-1$
			err(getLocalizationManager().getLocalizedTextString("lineNumberOutOfRange", args)); //$NON-NLS-1$
		}
		catch(AmbiguousException ae)
		{
			err(ae.getMessage());
		}
		catch(NoMatchException nme)
		{
			// TODO [mmorearty]: try to find a matching source file
			err(nme.getMessage());
		}
		catch(NullPointerException npe)
		{
			err(getLocalizationManager().getLocalizedTextString("noFilesFound")); //$NON-NLS-1$
		}
		catch(ParseException pe)
		{
			err(pe.getMessage());
		}
	}

	/**
	 * Fire up a session or await a connection from the socket if no
	 * URI was specified.
	 */
	void doRun() throws IOException
	{
		if (m_session != null)
		{
			err(getLocalizationManager().getLocalizedTextString("sessionInProgress")); //$NON-NLS-1$
			return;
		}

		SessionManager mgr = Bootstrap.sessionManager();

		if (hasMoreTokens())
		{
			if (!setLaunchURI(restOfLine()))
				return;
		}

		if (m_connectPort == null)
			mgr.startListening();

		try
		{
			if (m_connectPort != null) {
				out(getLocalizationManager().getLocalizedTextString("waitingToConnectToPlayer")); //$NON-NLS-1$
				m_session = mgr.connect(Integer.valueOf(m_connectPort), null);
			}
			else if (m_launchURI == null)
			{
				out(getLocalizationManager().getLocalizedTextString("waitingForPlayerToConnect")); //$NON-NLS-1$
				m_session = mgr.accept(null);
			}
			else
			{
				out(getLocalizationManager().getLocalizedTextString("launchingWithUrl") + m_newline + m_launchURI); //$NON-NLS-1$
				m_session = mgr.launch(m_launchURI, null, true, null, null);
			}

			// now see what happened
			if (m_session == null)
			{
				// shouldn't have gotten here
				throw new SocketTimeoutException();
			}
			else
			{
				out(getLocalizationManager().getLocalizedTextString("playerConnectedSessionStarting")); //$NON-NLS-1$
				initSession(m_session);

				// pause for a while during startup, don't let exceptions ripple outwards
				try { waitTilHalted(Isolate.DEFAULT_ID); } catch(Exception e) {}

				// pause for a while during startup, don't let exceptions ripple outwards
				try { waitForMetaData(); } catch(Exception e) {}

				setInitialSourceFile();

				out(getLocalizationManager().getLocalizedTextString("setBreakpointsThenResume")); //$NON-NLS-1$
				setPromptState(InitialPromptState.DONE, Isolate.DEFAULT_ID);

				// now poke to see if the player is good enough
				try
				{
					if (m_session.getPreference(SessionManager.PLAYER_SUPPORTS_GET) == 0 )
						err(m_newline + getLocalizationManager().getLocalizedTextString("warningNotAllCommandsSupported")); //$NON-NLS-1$
				}
				catch(Exception npe) {}
			}
		}
		catch (FileNotFoundException fnf)
		{
			Map<String, Object> args = new HashMap<String, Object>();
			args.put("uri", fnf.getLocalizedMessage()); //$NON-NLS-1$
			err(getLocalizationManager().getLocalizedTextString("fileDoesNotExist", args)); //$NON-NLS-1$
		}
		catch (SocketTimeoutException ste)
		{
			err(getLocalizationManager().getLocalizedTextString("failedToConnect")); //$NON-NLS-1$
		}
		catch (IOException io)
		{
			err(io.getLocalizedMessage());
		}
		finally
		{
			// turn off listening, to allow other session to connect
			if (m_connectPort == null)
				mgr.stopListening();
		}
	}
	
	/**
	 * Fire up a session or await a connection from the socket if no
	 * URI was specified.
	 */
	void doConnect() throws IOException
	{
		int port = 0;
		if (hasMoreTokens()) 
		{
			try
			{
				port = nextIntToken();				
			}
			catch (NumberFormatException ex)
			{
				err(ex.getLocalizedMessage());
			}
		}
		else
		{
			port = DProtocol.DEBUG_CONNECT_PORT;
		}
		
		if (port > 0)
		{
			m_connectPort = String.valueOf(port);
			doRun();
		}
	}

	/**
	 * When we begin a debugging session, it would be nice if the default file
	 * for the "list" command etc. was the user's main MXML application file.
	 * There is no good way to really figure out what that file is, but we can
	 * certainly take a guess.
	 */
	private void setInitialSourceFile()
	{
		int largestAuthoredId = -1;
		SourceFile[] files = m_fileInfo.getFileList(m_activeIsolate);
		for (int i=0; i<files.length; ++i)
		{
			SourceFile sf = files[i];
			if (sf.getId() > largestAuthoredId && getFileType(sf) == AUTHORED_FILE)
				largestAuthoredId = sf.getId();
		}
		if (largestAuthoredId != -1)
			setListingPosition(largestAuthoredId, 1, m_activeIsolate);
	}

	private boolean setLaunchURI(String launchURI)
	{
		if (launchURI != null)
		{
			SessionManager mgr = Bootstrap.sessionManager();

			// If doing fdbunit, we always try to do launch(), even on platforms
			// that say they don't support it
			if (!mgr.supportsLaunch() && System.getProperty("fdbunit") == null) //$NON-NLS-1$
			{
				err(getLocalizationManager().getLocalizedTextString("manuallyLaunchPlayer")); //$NON-NLS-1$
				return false;
			}

			// check for special form of URI when in fullname mode, since we can't pass http: in this mode?!?
			if (m_fullnameOption)
			{
				if (launchURI.startsWith("//")) //$NON-NLS-1$
					launchURI = "http:"+launchURI; //$NON-NLS-1$
			}
		}

		m_launchURI = launchURI;
		return true;
	}

	// set the URI
	void doFile()
	{
		if (!hasMoreTokens())
			setLaunchURI(null);
		else
			setLaunchURI(restOfLine());
	}

	void doSource()
	{
		String name = ""; //$NON-NLS-1$
		try
		{
			name = nextToken();
			FileReader f = new FileReader(name);

			// push our current source onto the stack and open the new one
			pushStream(m_in);
			m_in = new LineNumberReader(f);
		}
		catch(NullPointerException npe)
		{
			err(getLocalizationManager().getLocalizedTextString("sourceCommandRequiresPath")); //$NON-NLS-1$
		}
		catch(NoSuchElementException nse)
		{
			err(getLocalizationManager().getLocalizedTextString("sourceCommandRequiresPath")); //$NON-NLS-1$
		}
		catch(FileNotFoundException fnf)
		{
			Map<String, Object> args = new HashMap<String, Object>();
			args.put("filename", name); //$NON-NLS-1$
			err(getLocalizationManager().getLocalizedTextString("fileNotFound", args)); //$NON-NLS-1$
		}
	}

	void listFault(String f)
	{
		StringBuilder sb = new StringBuilder();
		appendFaultTitles(sb);
		appendFault(sb, f);

		out( sb.toString() );
	}

	void appendFault(StringBuilder sb, String f)
	{
		sb.append(f);

		int space = 30 - f.length();
		repeat(sb, ' ', space);

		boolean stop = m_faultTable.is(f, "stop"); //$NON-NLS-1$
		boolean print = m_faultTable.is(f, "print"); //$NON-NLS-1$

		sb.append( stop ? "Yes" : "No" ); //$NON-NLS-1$ //$NON-NLS-2$
		repeat(sb, ' ', stop ? 0 : 1);

		repeat(sb, ' ', 5);

		sb.append( print ? "Yes" : "No" ); //$NON-NLS-1$ //$NON-NLS-2$
		repeat(sb, ' ', print ? 0 : 1);

		// description
		repeat(sb, ' ', 7);

		String desc = m_faultTable.getDescription(f);
		sb.append(desc);
		sb.append(m_newline);
	}

	void appendFaultTitles(StringBuilder sb)
	{
		sb.append("Fault                         Stop    Print     Description"+m_newline); //$NON-NLS-1$
		sb.append("-----                         ----    -----     -----------"+m_newline); //$NON-NLS-1$
	}

	/**
	 * Controls the configuration of what occurs when a
	 * fault is encountered
	 */
	void doHandle()
	{
		// should be at least on arg
		if (!hasMoreTokens())
			err(getLocalizationManager().getLocalizedTextString("argumentRequired")); //$NON-NLS-1$
		else
		{
			// poor man's fix for supporting 'all' option
			String faultName = nextToken();
			Object[] names = new Object[] { faultName };

			// replace the single name with all of them
			if (faultName.equalsIgnoreCase("all")) //$NON-NLS-1$
				names = m_faultTable.names();

			// make sure we know about at least one
		    if (!m_faultTable.exists((String)names[0]))
				err(getLocalizationManager().getLocalizedTextString("unrecognizedFault")); //$NON-NLS-1$
			else
			{
				if (!hasMoreTokens())
					listFault((String)names[0]);
				else
				{
					String action = null;
					try
					{
						while(hasMoreTokens())
						{
							action = nextToken();
							for(int i=0; i<names.length; i++)
								m_faultTable.action((String)names[i], action);
						}
					}
					catch(IllegalArgumentException iae)
					{
						Map<String, Object> args = new HashMap<String, Object>();
						args.put("action", action); //$NON-NLS-1$
						err(getLocalizationManager().getLocalizedTextString("unrecognizedAction", args)); //$NON-NLS-1$
					}
				}
			}
		}
	}

	/**
	 * Do the commands command!  This attaches a series of lines of text input by the user
	 * to a particular breakpoint, with the intention of exeuting these lines when the
	 * breakpoint is hit.
	 */
	void doCommands() throws IOException
	{
		try
		{
			int id = -1;
			if (hasMoreTokens())
				id = nextIntToken();
			else
				id = propertyGet(BPNUM);

			// get the breakpoint
			int at = breakpointIndexOf(id);
			BreakAction a = breakpointAt(at);

			// ready it
			a.clearCommands();
			a.setSilent(false);

			// now just pull the commands as they come while not end
			String line = null;
			boolean first = true;
			boolean isEnd = false;

			Map<String, Object> args = new HashMap<String, Object>();
			args.put("breakpointNumber", Integer.toString(id)); //$NON-NLS-1$
			out(getLocalizationManager().getLocalizedTextString("typeCommandsForBreakpoint", args)); //$NON-NLS-1$

			do
			{
				displayCommandPrompt();
				line = readLine().trim();
			    isEnd = line.equalsIgnoreCase("end"); //$NON-NLS-1$

				if (!isEnd)
				{
					if (first && line.equalsIgnoreCase("silent")) //$NON-NLS-1$
						a.setSilent(true);
					else
						a.addCommand(line);
				}
				first = false;
			}
			while(!isEnd);
		}
		catch(IndexOutOfBoundsException iob)
		{
			Map<String, Object> args = new HashMap<String, Object>();
			args.put("breakpointNumber", m_currentToken); //$NON-NLS-1$
			err(getLocalizationManager().getLocalizedTextString("noBreakpointNumber", args)); //$NON-NLS-1$
		}
		catch(NumberFormatException nfe)
		{
			Map<String, Object> args = new HashMap<String, Object>();
			args.put("token", m_currentToken); //$NON-NLS-1$
			err(getLocalizationManager().getLocalizedTextString("badBreakpointNumber", args)); //$NON-NLS-1$
		}
		catch(NullPointerException npe)
		{
			err(getLocalizationManager().getLocalizedTextString("commandFailed")); //$NON-NLS-1$
		}
	}

	/**
	 * Apply or remove conditions to a breakpoint.
	 */
	void doCondition() throws IOException
	{
		try
		{
			// must have a breakpoint number
			int id = nextIntToken();

			// get the breakpoint
			int at = breakpointIndexOf(id);
			BreakAction a = breakpointAt(at);

			// no more parms means to clear it
			if (hasMoreTokens())
			{
				// now just pull the commands as they come while not end
				String line = restOfLine();

				// build an expression and attach it to the breakpoint
				ValueExp exp = parseExpression(line);

				// warn about the assignment!
				if ( exp.containsAssignment() && !yesNoQuery(getLocalizationManager().getLocalizedTextString("askExpressionContainsAssignment")) ) //$NON-NLS-1$
					throw new IllegalAccessException("="); //$NON-NLS-1$

				a.setCondition(exp, line);
			}
			else
			{
				a.clearCondition();   // clear it
				Map<String, Object> args = new HashMap<String, Object>();
				args.put("breakpointNumber", Integer.toString(id)); //$NON-NLS-1$
				out(getLocalizationManager().getLocalizedTextString("breakpointNowUnconditional", args)); //$NON-NLS-1$
			}
		}
		catch(IllegalAccessException iae)
		{
			err(getLocalizationManager().getLocalizedTextString("breakpointNotChanged")); //$NON-NLS-1$
		}
		catch(IndexOutOfBoundsException iob)
		{
			Map<String, Object> args = new HashMap<String, Object>();
			args.put("breakpointNumber", m_currentToken); //$NON-NLS-1$
			err(getLocalizationManager().getLocalizedTextString("noBreakpointNumber", args)); //$NON-NLS-1$
		}
		catch(NumberFormatException nfe)
		{
			Map<String, Object> args = new HashMap<String, Object>();
			args.put("token", m_currentToken); //$NON-NLS-1$
			err(getLocalizationManager().getLocalizedTextString("badBreakpointNumber", args)); //$NON-NLS-1$
		}
		catch(NullPointerException npe)
		{
			err(getLocalizationManager().getLocalizedTextString("commandFailed")); //$NON-NLS-1$
		}
	}

	/**
	 * Request to add a new watchpoint
	 * This may result in one of two things happening
	 * (1) a new watchpoint could be added or
	 * (2) an existing watchpoint may be modified.
	 *
	 * The watch, awatch, and rwatch commands will set a watchpoint on the
	 * given expression. The different commands control the read/write aspect
	 * of the watchpoint.
	 *
	 * awatch will trigger a break if the expression is read or written.
	 * rwatch will trigger a break if the expression is read.
	 * watch will trigger a break if the expression is written.
	 */
	void doWatch(boolean read, boolean write) throws PlayerDebugException
	{
		try
		{
			if (read)
			{
				err("Only break-on-write watchpoints are supported."); //$NON-NLS-1$
				return;
			}

			StringBuilder sb = new StringBuilder();

			/* pull the rest of the line */
			String s = restOfLine();

			int flags = 3;
			if(read && write) flags = WatchKind.READWRITE;
			else if(read) flags = WatchKind.READ;
			else if(write) flags = WatchKind.WRITE;

			IsolateSession workerSession = m_session.getWorkerSession(m_activeIsolate);
			// snapshot of our existing list
			Watch[] list = workerSession.getWatchList();

			// We need to separate the front part the 'a.b' in 'a.b.c' 
			// of the expression to resolve it into a variable 
			// We usually get back a VariableFacade which contains
			// the context id (i.e the variable id) and the member name.
			ValueExp expr = parseExpression(s);
			VariableFacade result = (VariableFacade)(evalExpression(expr, m_activeIsolate).value);

			// extract the 2 pieces and get the raw variable.
			long varId = result.getContext(); // TODO fix this???  -mike
			String memberName = result.getName();
			Value v = workerSession.getValue(varId);

			// attempt to set.
			Watch w = m_session.setWatch(v, memberName, flags);
			if (w == null)
			{
				// failed
				Map<String, Object> args = new HashMap<String, Object>();
				args.put("expression", s); //$NON-NLS-1$
				err(getLocalizationManager().getLocalizedTextString("watchpointCouldNotBeSet", args)); //$NON-NLS-1$
			}
			else
			{
				// if modified then lists are same length
				// otherwise 1 will be added
				Watch[] newList = workerSession.getWatchList();
				if (newList.length == list.length)
				{
					// modified, lets locate the one that changed
					// and reset it
					int at = missingWatchpointIndexOf(newList);
					WatchAction a = null;
					try	
					{ 
						a = watchpointAt(at); 
					} 
					catch(ArrayIndexOutOfBoundsException aio)
					{
						// this is pretty bad it means the player thinks we have a watchpoint
						// but we don't have a record of it.  So let's create a new one
						// and hope that we are now in sync with the player.
						a = new WatchAction(w);
					}

					// modify our view of the watchpoint
					int id = a.getId();
					a.resetWatch(w);

					Map<String, Object> args = new HashMap<String, Object>();
					args.put("watchpointNumber", Integer.toString(id)); //$NON-NLS-1$
					args.put("expression", s); //$NON-NLS-1$
					args.put("watchpointMode", getWatchpointModeString(a.getKind())); //$NON-NLS-1$
					sb.append(getLocalizationManager().getLocalizedTextString("changedWatchpointMode", args)); //$NON-NLS-1$
				}
				else
				{
					// newly added
					WatchAction a = new WatchAction(w);
					watchpointAdd(a);

					int which = a.getId();
					Map<String, Object> args = new HashMap<String, Object>();
					args.put("watchpointNumber", Integer.toString(which)); //$NON-NLS-1$
					args.put("expression", s); //$NON-NLS-1$
					sb.append(getLocalizationManager().getLocalizedTextString("createdWatchpoint", args)); //$NON-NLS-1$
				}
				out(sb.toString());
			}
		}
		catch(ArrayIndexOutOfBoundsException aio)
		{
			// We should really do some cleanup after this exception
			// since it most likely means we can't find the watchpoint
			// that was just modified, therefore our watchlists are
			// out of sync with those of the API.
			err(getLocalizationManager().getLocalizedTextString("badWatchpointNumber")); //$NON-NLS-1$
		}
		catch(NullPointerException npe)
		{
			err(getLocalizationManager().getLocalizedTextString("couldNotEvaluate")); //$NON-NLS-1$
		}
		catch(ClassCastException cce)
		{
			err(getLocalizationManager().getLocalizedTextString("couldNotResolveExpression")); //$NON-NLS-1$
		}
	}

	WatchAction watchpointAt(int at)			{ return m_watchpoints.get(at); }
	boolean		watchpointAdd(WatchAction a)	{ return m_watchpoints.add(a); 	}
	int			watchpointCount()				{ return m_watchpoints.size(); 	}

	int watchpointIndexOf(int id)
	{
		int size = watchpointCount();
		for(int i = 0; i < size; i++)
		{
			WatchAction b = watchpointAt(i);
			if(b.getId() == id)
				return i;
		}

		return -1;
	}

	void removeAllWatchpoints() throws NotConnectedException
	{
		while(watchpointCount() > 0)
			removeWatchpointAt(0);
	}

	void removeWatchpointAt(int at) throws NotConnectedException
	{
		WatchAction b = watchpointAt(at);
		boolean worked = false;

		try { worked = (m_session.clearWatch(b.getWatch()) == null) ? false : true; } catch(NoResponseException nre) {}

		if(!worked)
		{
			Map<String, Object> args = new HashMap<String, Object>();
			args.put("variable", b.getExpr() ); //$NON-NLS-1$
			err(getLocalizationManager().getLocalizedTextString("couldNotFindWatchpoint", args)); //$NON-NLS-1$
		}

		// remove in any event
		m_watchpoints.remove(at);
	}

	String getWatchpointModeString(int flags) 
	{
		switch(flags) 
		{
			case 1:
				return getLocalizationManager().getLocalizedTextString("watchpointMode_read"); //$NON-NLS-1$
			case 2:
				return getLocalizationManager().getLocalizedTextString("watchpointMode_write"); //$NON-NLS-1$
			case 3:
				return getLocalizationManager().getLocalizedTextString("watchpointMode_readWrite"); //$NON-NLS-1$
		}
		return ""; //$NON-NLS-1$
	}

	/**
	 * Locate the index of a WatchAction that does not
	 * have a corresponding Watch in the given list. 
	 * 
	 * WARNING: this call can be very expensive but
	 * it is assumed that a.list and watchpointCount()
	 * are both small. 
	 */
	int missingWatchpointIndexOf(Watch[] a)
	{
		int size = watchpointCount();
		int at = -1;
		for(int i=0; i<size && at<0; i++)
		{
			WatchAction action = watchpointAt(i);
			Watch w = action.getWatch();
			
			// now scan the list of watches looking for a hit
			int hit = -1;
			for(int j=0; j<a.length && hit<0; j++)
			{
				if (w == a[j])
					hit = j;
			}

			// can't find the watch object corresponding to our
			// watchpoint in list of session watches.
			if (hit < 0)
				at = i;
		}

		return at;
	}

	/**
	 * Display command
	 */
	void doDisplay()
	{
		try
		{
			if (!hasMoreTokens())
				doInfoDisplay();
			else
			{
				// followed by an expression (i.e. a line we just pull in)
				String s = restOfLine();

				// first parse it, then attempt to evaluate the expression
				ValueExp expr = parseExpression(s);

				// make sure no assignment
				if ( expr.containsAssignment() )
					throw new IllegalAccessException();

				// it worked so create a new DisplayAction and then add it in

				DisplayAction b = new DisplayAction(expr, s, m_activeIsolate);
				b.setEnabled(true);
				displayAdd(b);
			}
		}
		catch(IllegalAccessException iae)
		{
			err(getLocalizationManager().getLocalizedTextString("noSideEffectsAllowed")); //$NON-NLS-1$
		}
		catch(NullPointerException npe)
		{
			// already handled by parseExpression
		}
	}

	/**
	 * Remove auto-display expressions
	 */
	void doUnDisplay() throws IOException
	{
		try
		{
			if (!hasMoreTokens())
			{
				// no args means delete all displays, last chance...
				if (yesNoQuery(getLocalizationManager().getLocalizedTextString("askDeleteAllAutoDisplay"))) //$NON-NLS-1$
				{
					int count = displayCount();
					for(int i=count-1; i>-1; i--)
					{
						displayRemoveAt(i);
					}
				}
			}
			else
			{
				while(hasMoreTokens())
				{
					int id = nextIntToken();
					int at = displayIndexOf(id);
					displayRemoveAt(at);
				}
			}
		}
		catch(IndexOutOfBoundsException iob)
		{
			Map<String, Object> args = new HashMap<String, Object>();
			args.put("displayNumber", m_currentToken); //$NON-NLS-1$
			err(getLocalizationManager().getLocalizedTextString("noDisplayNumber", args)); //$NON-NLS-1$
		}
		catch(NumberFormatException nfe)
		{
			Map<String, Object> args = new HashMap<String, Object>();
			args.put("token", m_currentToken); //$NON-NLS-1$
			err(getLocalizationManager().getLocalizedTextString("badDisplayNumber", args)); //$NON-NLS-1$
		}
		catch(NullPointerException npe)
		{
			err(getLocalizationManager().getLocalizedTextString("commandFailed")); //$NON-NLS-1$
		}
	}

	/**
	 * Enabled breakpoints and disaplays
	 */
	void doDisable() throws AmbiguousException, NotConnectedException
	{
		waitTilHalted(m_activeIsolate);

		try
		{
			if (!hasMoreTokens())
			{
				disableAllBreakpoints();
			}
			else
			{
				// optionally specify  'display' or 'breakpoint'
				String arg = nextToken();
				int cmd = disableCommandFor(arg);
				int id = -1;
                if (cmd == CMD_DISPLAY)
                {
                    doDisableDisplay();
                }
                else if (cmd == CMD_BREAK && !hasMoreTokens())
                {
                    disableAllBreakpoints();
                }
				else
				{
					if (cmd == CMD_BREAK)
						id = nextIntToken();  // ignore and get next number token
					else
						id = Integer.parseInt(arg);

					do
					{
						int at = breakpointIndexOf(id);
						disableBreakpointAt(at);

						if (hasMoreTokens())
							id = nextIntToken();
						else
							id = -1;

						// keep going till we're blue in the face; also note that we cache'd a copy of locations
						// so that breakpoint numbers are consistent.
					}
					while( id > -1 );
				}
			}
		}
		catch(IndexOutOfBoundsException iob)
		{
			Map<String, Object> args = new HashMap<String, Object>();
			args.put("breakpointNumber", m_currentToken); //$NON-NLS-1$
			err(getLocalizationManager().getLocalizedTextString("noBreakpointNumber", args)); //$NON-NLS-1$
		}
		catch(NumberFormatException nfe)
		{
			Map<String, Object> args = new HashMap<String, Object>();
			args.put("token", m_currentToken); //$NON-NLS-1$
			err(getLocalizationManager().getLocalizedTextString("badBreakpointNumber", args)); //$NON-NLS-1$
		}
		catch(NullPointerException npe)
		{
			err(getLocalizationManager().getLocalizedTextString("commandFailed")); //$NON-NLS-1$
		}
	}

	void disableAllBreakpoints() throws NotConnectedException {
		// disables all breakpoints,
		int count = breakpointCount();
		for(int i=0; i<count; i++)
			disableBreakpointAt(i);
	}

	// disable a breakpoint
	void disableBreakpointAt(int at) throws NotConnectedException
	{
		BreakAction a = breakpointAt(at);
		a.setEnabled(false);
		breakDisableRequest(a.getLocations());
	}

	void doDisableDisplay() { doEnableDisableDisplay(false); }

	void doEnableDisableDisplay(boolean enable)
	{
		try
		{
			if (!hasMoreTokens())
			{
				// means do all!
				int size = displayCount();
				for(int i=0; i<size; i++)
					displayAt(i).setEnabled(enable);
			}
			else
			{
				// read ids until no more
				while( (hasMoreTokens()) )
				{
					int id = nextIntToken();
					int at = displayIndexOf(id);
					DisplayAction a = displayAt(at);
					a.setEnabled(enable);
				}
			}
		}
		catch(IndexOutOfBoundsException iob)
		{
			Map<String, Object> args = new HashMap<String, Object>();
			args.put("displayNumber", m_currentToken); //$NON-NLS-1$
			err(getLocalizationManager().getLocalizedTextString("noDisplayNumber", args)); //$NON-NLS-1$
		}
		catch(NumberFormatException nfe)
		{
			Map<String, Object> args = new HashMap<String, Object>();
			args.put("token", m_currentToken); //$NON-NLS-1$
			err(getLocalizationManager().getLocalizedTextString("badDisplayNumber", args)); //$NON-NLS-1$
		}
	}

	/**
	 * Enables breakpoints (forever, one-shot hit or auto delete) and displays
	 */
	void doEnable() throws AmbiguousException, NotConnectedException
	{
		waitTilHalted(m_activeIsolate);

		try
		{
			if (!hasMoreTokens())
			{
				enableAllBreakpoints();
			}
			else
			{
				// optionally specify  'display' or 'breakpoint'
				String arg = nextToken();
				int cmd = enableCommandFor(arg);
				int id = -1;
				boolean autoDelete = false;
				boolean autoDisable = false;
				if (cmd == CMD_DISPLAY)
				{
					doEnableDisplay();
				}
				else if ((cmd == CMD_BREAK) && !hasMoreTokens())
				{
					enableAllBreakpoints();
				}
				else
				{
					if (cmd == CMD_BREAK)
						id = nextIntToken();  // ignore and get next number token
					else if (cmd == CMD_DELETE)
					{
						autoDelete = true;
						id = nextIntToken();  // set and get next number token
					}
					else if (cmd == ENABLE_ONCE_CMD)
					{
						autoDisable = true;
						id = nextIntToken();  // set and get next number token
					}
					else
						id = Integer.parseInt(arg);

					boolean worked = true;
					do
					{
						int at = breakpointIndexOf(id);
						worked = enableBreakpointAt(at, autoDisable, autoDelete);

						if (hasMoreTokens())
							id = nextIntToken();
						else
							id = -1;

						// keep going till we're blue in the face; also note that we cache'd a copy of locations
						// so that breakpoint numbers are consistent.
					}
					while( worked && id > -1 );

					if (!worked)
					{
						Map<String, Object> args = new HashMap<String, Object>();
						args.put("breakpointNumber", Integer.toString(id)); //$NON-NLS-1$
						err(getLocalizationManager().getLocalizedTextString("breakpointLocationNoLongerExists", args)); //$NON-NLS-1$
					}
				}
			}
		}
		catch(IndexOutOfBoundsException iob)
		{
			Map<String, Object> args = new HashMap<String, Object>();
			args.put("breakpointNumber", m_currentToken); //$NON-NLS-1$
			err(getLocalizationManager().getLocalizedTextString("noBreakpointNumber", args)); //$NON-NLS-1$
		}
		catch(NumberFormatException nfe)
		{
			Map<String, Object> args = new HashMap<String, Object>();
			args.put("token", m_currentToken); //$NON-NLS-1$
			err(getLocalizationManager().getLocalizedTextString("badBreakpointNumber", args)); //$NON-NLS-1$
		}
		catch(NullPointerException npe)
		{
			err(getLocalizationManager().getLocalizedTextString("commandFailed")); //$NON-NLS-1$
		}
	}

	void enableAllBreakpoints() throws NotConnectedException {
		// enables all breakpoints
		int count = breakpointCount();
		int tally = 0;
		for(int i=0; i<count; i++)
			tally += enableBreakpointAt(i) ? 1 : 0;
		
		// mention that not all was good
		if (tally != count)
			err(getLocalizationManager().getLocalizedTextString("notAllBreakpointsEnabled")); //$NON-NLS-1$
	}

	// request to enable a breakpoint
	// @return false if we couldn't enable it.
	boolean enableBreakpointAt(int at) throws NotConnectedException { return enableBreakpointAt(at, false, false); }

	boolean enableBreakpointAt(int at, boolean autoDisable, boolean autoDelete) throws NotConnectedException
	{
		return enableBreakpoint(breakpointAt(at), autoDisable, autoDelete);
	}
	
	boolean enableBreakpoint(BreakAction a, boolean autoDisable, boolean autoDelete) throws NotConnectedException
	{
		boolean retval = false;
		Location l = a.getLocation();   // use the first location as a source file / line number template 
		if (l != null)
		{
			LocationCollection col = enableBreak(l.getFile(), l.getLine(), l.getIsolateId());
			if (!col.isEmpty())
			{
				a.setEnabled(true);
				a.setLocations(col);
				a.setAutoDisable(autoDisable);
				a.setAutoDelete(autoDelete);
				a.setSingleSwf(false);
				a.setStatus(BreakAction.RESOLVED);
				retval = true;
			}
		}
		return retval;
	}

	void doEnableDisplay() { doEnableDisableDisplay(true); }

    /* Print working directory */
    void doPWD()
    {
        out(System.getProperty("user.dir")); //$NON-NLS-1$
    }

    /* Display or change current file */
    void doCF()
    {
        try
        {
            int module = propertyGet(LIST_MODULE);
			int currentLine = propertyGet(LIST_LINE);
			int worker = propertyGet(LIST_WORKER);

            if (hasMoreTokens())
            {
                String arg = nextToken();
                module = parseFileArg(module, arg);
				currentLine = 1;
                setListingPosition(module, currentLine, worker);
             }

            SourceFile sourceFile = m_fileInfo.getFile(module, worker);
			StringBuilder sb = new StringBuilder();
			sb.append(sourceFile.getName());
			sb.append('#');
			sb.append(sourceFile.getId());
			sb.append(':');
			sb.append(currentLine);
			out( sb.toString() );
        }
		catch(NullPointerException npe)
		{
			err(getLocalizationManager().getLocalizedTextString("noFilesFound")); //$NON-NLS-1$
		}
		catch(ParseException pe)
		{
			err(pe.getMessage());
		}
		catch(AmbiguousException ae)
		{
			err(ae.getMessage());
		}
		catch(NoMatchException nme)
		{
			err(nme.getMessage());
		}
    }

 	/* Terminates current debugging sesssion */
	void doKill() throws IOException
	{
		if (m_session == null)
			err(getLocalizationManager().getLocalizedTextString("programNotBeingRun")); //$NON-NLS-1$
		else
		{
			if (yesNoQuery(getLocalizationManager().getLocalizedTextString("askKillProgram"))) //$NON-NLS-1$
				exitSession();
		}
	}

	/* Terminates fdb */
	boolean doQuit() throws IOException
	{
		boolean quit = false;

		// no session, no questions
		if (m_session == null)
			quit = true;
		else
		{
			quit = yesNoQuery(getLocalizationManager().getLocalizedTextString("askProgramIsRunningExitAnyway")); //$NON-NLS-1$
			if (quit)
				exitSession();
		}
		return quit;
	}

	/* (non-Javadoc)
	 * @see flash.tools.debugger.SourceLocator#locateSource(java.lang.String, java.lang.String, java.lang.String)
	 */
	public InputStream locateSource(String path, String pkg, String name)
	{
		File f = null;
		boolean exists = false;
		String pkgPlusName;

		if ((pkg != null && pkg.length() > 0))
			pkgPlusName = pkg + File.separator + name;
		else
			pkgPlusName = null;

		Iterator<String> iter = m_sourceDirectories.iterator();
		while (iter.hasNext())
		{
			String dir = iter.next();

			// new File("", filename) searches the root dir -- that's not what we want!
			if (dir.equals("")) //$NON-NLS-1$
				dir = "."; //$NON-NLS-1$

			// look for sourcedir\package\filename
			if (pkgPlusName != null)
			{
				f = new File(dir, pkgPlusName);
				exists = f.exists();
			}

			// look for sourcedir\filename
			if (!exists)
			{
				f = new File(dir, name);
				exists = f.exists();
			}

			if (exists)
			{
				try
				{
					return new FileInputStream(f);
				}
				catch (FileNotFoundException e)
				{
					e.printStackTrace(); // shouldn't happen
				}
			}
		}

		return null;
	}

	/* (non-Javadoc)
	 * @see flash.tools.debugger.SourceLocator#getChangeCount()
	 */
	public int getChangeCount()
	{
		return m_sourceDirectoriesChangeCount;
	}

	private void doDirectory() throws IOException
	{
		if (hasMoreTokens())
		{
			// File.separator is ";" on Windows or ":" on Mac
			StringTokenizer dirs = new StringTokenizer(restOfLine(), File.pathSeparator);
			int insertPos = 0;

			while (dirs.hasMoreTokens())
			{
				String dir = dirs.nextToken();
				if (dir.length() > 2 && dir.charAt(0) == '"' && dir.charAt(dir.length()-1) == '"')
					dir = dir.substring(1, dir.length() - 1);
				dir = dir.trim();
				if (dir.length() > 0)
				{
					// For Unix and Mac, we want to escape "~" and "$HOME"
					if (!System.getProperty("os.name").toLowerCase().startsWith("windows")) //$NON-NLS-1$ //$NON-NLS-2$
					{
						// If the string starts with "~", or contains any environment variables
						// such as "$HOME", we need to escape those
						if (dir.matches("^.*[~$].*$")) //$NON-NLS-1$
						{
							try
							{
								Process p = Runtime.getRuntime().exec(
										new String[] { "/bin/sh", "-c", "echo " + dir} ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
								BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
								String line = r.readLine();
								if (line != null)
								{
									line = line.trim();
									if (line.length() > 0)
										dir = line;
								}
							}
							catch (IOException e)
							{
								// ignore
							}
						}
					}

					try
					{
						dir = new File(dir).getCanonicalPath();
						m_sourceDirectories.add(insertPos++, dir);
					}
					catch (IOException e)
					{
						err(e.getMessage());
					}
				}
			}
			++m_sourceDirectoriesChangeCount;
		}
		else
		{
			if (yesNoQuery(getLocalizationManager().getLocalizedTextString("askReinitSourcePath"))) //$NON-NLS-1$
			{
				initSourceDirectoriesList();
			}
		}

		doShowDirectories();
	}

	public void initSourceDirectoriesList()
	{
		m_sourceDirectories.clear();
		File flexHome = getFlexHomeDirectory();
		if (flexHome != null)
		{
			try
			{
				File projectsDir = new File(flexHome, "frameworks/projects"); //$NON-NLS-1$
				File[] files = projectsDir.listFiles();
				if (files != null)
				{
					for (int i=0; i<files.length; ++i)
					{
						if (files[i].isDirectory())
						{
							File srcDir = new File(files[i], "src"); //$NON-NLS-1$
							if (srcDir.isDirectory())
							{
								m_sourceDirectories.add(srcDir.getCanonicalPath());
							}
						}
					}
				}
			}
			catch (IOException e)
			{
				// ignore
			}
		}
		++m_sourceDirectoriesChangeCount;
	}

	/**
	 * Returns the Flex home directory.  This is based on the <code>application.home</code>
	 * Java system property if present, or the current directory otherwise.
	 * This directory is one up from the "bin" and "lib" directories.  For example,
	 * <code>&lt;flexhome&gt;/lib/fdb.jar</code> can be used to refer to the fdb jar.
	 */
	protected File getFlexHomeDirectory()
	{
		if (!m_initializedFlexHomeDirectory)
		{
			m_initializedFlexHomeDirectory = true;
			m_flexHomeDirectory = new File("."); // default in case the following logic fails //$NON-NLS-1$
			String flexHome = System.getProperty("application.home"); //$NON-NLS-1$
			if (flexHome != null && flexHome.length() > 0)
			{
				try
				{
					m_flexHomeDirectory = new File(flexHome).getCanonicalFile();
				}
				catch (IOException e)
				{
					// ignore
				}
			}
		}

		return m_flexHomeDirectory;
	}

	protected String getenv(String var)
	{
		String[] cmd;
		if (System.getProperty("os.name").toLowerCase().startsWith("windows")) //$NON-NLS-1$ //$NON-NLS-2$
		{
			cmd = new String[] { "cmd.exe", "/c", "echo", "%" + var + "%" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
		}
		else
		{
			cmd = new String[] { "/bin/sh", "-c", "echo $" + var }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		}

		try
		{
			Process p = Runtime.getRuntime().exec(cmd);
			BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
			String line = r.readLine();
			if (line != null && line.length() > 0)
			{
				return line;
			}
		}
		catch (IOException e)
		{
			// ignore
		}
		
		return null;
	}

	private void doCatch() throws NotConnectedException, NotSuspendedException, NoResponseException
	{
		/* wait a bit if we are not halted */
		waitTilHalted(m_activeIsolate);

        String typeToCatch = null;

		/* currentXXX may NOT be invalid! */
		if (!hasMoreTokens())
		{
			err("Catch requires an exception name."); //$NON-NLS-1$
			return;
		}

        typeToCatch = nextToken();
        if (typeToCatch == null || typeToCatch.length() == 0)
        {
        	err("Illegal argument"); //$NON-NLS-1$
        	return;
        }

        Value type = null;
        if (typeToCatch.equals("*")) //$NON-NLS-1$
        {
        	typeToCatch = null;
        }
        else
        {
	        type = getSession().getWorkerSession(m_activeIsolate).getGlobal(typeToCatch);
	        if (type == null)
	        {
	        	err("Type not found."); //$NON-NLS-1$
	        	return;
	        }

	        String typeName = type.getTypeName();
	        int at = typeName.indexOf('@');
	        if (at != -1)
	        	typeName = typeName.substring(0, at);
	        if (!typeName.endsWith("$")) //$NON-NLS-1$
	        {
	        	err("Not a type: " + type); //$NON-NLS-1$
	        	return;
	        }
        }

        CatchAction c;
		try {
			c = addCatch(typeToCatch);
		} catch (NotSupportedException e) {
			e.printStackTrace();
			return;
		}

    	Map<String, Object> args = new HashMap<String, Object>();
    	args.put("id", c.getId()); //$NON-NLS-1$
    	c.getId();
	}

	private CatchAction addCatch(String typeToCatch) throws NotSupportedException, NoResponseException {
		CatchAction c = new CatchAction(typeToCatch);
		catchpointAdd(c);
		return c;
	}

	CatchAction catchpointAt(int at)			{ return m_catchpoints.get(at); }
	int			catchpointCount()				{ return m_catchpoints.size(); 	}

	boolean catchpointAdd(CatchAction a) throws NotSupportedException, NoResponseException
	{
		if (catchpointCount() == 0)
			getSession().getWorkerSession(m_activeIsolate).breakOnCaughtExceptions(true);

		return m_catchpoints.add(a);
	}

	int catchpointIndexOf(int id)
	{
		int size = catchpointCount();
		for(int i = 0; i < size; i++)
		{
			CatchAction c = catchpointAt(i);
			if(c.getId() == id)
				return i;
		}

		return -1;
	}

	void removeAllCatchpoints() throws NotConnectedException
	{
		while(catchpointCount() > 0)
			removeCatchpointAt(0);
	}

	void removeCatchpointAt(int at) throws NotConnectedException
	{
		// remove in any event
		m_catchpoints.remove(at);

		if (catchpointCount() == 0) {
			try {
				getSession().getWorkerSession(m_activeIsolate).breakOnCaughtExceptions(false);
			} catch (NotSupportedException e) {
			} catch (NoResponseException e) {
			}
		}
	}

	void doUnknown(String s) { doUnknown("", s); } //$NON-NLS-1$

	void doUnknown(String what, String s)
	{
		Map<String, Object> args = new HashMap<String, Object>();
		String formatString;
		args.put("command", s); //$NON-NLS-1$
		if (what == null || what.equals("")) //$NON-NLS-1$
		{
			formatString = "unknownCommand"; //$NON-NLS-1$
			args.put("commandCategory", what); //$NON-NLS-1$
		}
		else
		{
			formatString = "unknownSubcommand"; //$NON-NLS-1$
		}
		err(getLocalizationManager().getLocalizedTextString(formatString, args));
	}

	/**
	 * Process the incoming debug event queue
	 */
	void processEvents() throws NotConnectedException
	{
		boolean requestResume = false;
		int breakIsolate = Isolate.DEFAULT_ID;
		boolean requestHalt = getIsolateState(breakIsolate).m_requestHalt;

		while(m_session != null && m_session.getEventCount() > 0)
		{
			DebugEvent e = m_session.nextEvent();

			if (e instanceof TraceEvent)
			{
				dumpTraceLine(e.information);
			}
			else if (e instanceof SwfLoadedEvent)
			{
				handleSwfLoadedEvent((SwfLoadedEvent)e);
			}
			else if (e instanceof SwfUnloadedEvent)
			{
				handleSwfUnloadedEvent((SwfUnloadedEvent)e);
			}
			else if (e instanceof IsolateCreateEvent) {
				handleIsolateCreateEvent((IsolateCreateEvent)e);
			}
			else if (e instanceof IsolateExitEvent) {
				handleIsolateExitEvent((IsolateExitEvent)e);
			}
			else if (e instanceof BreakEvent)
			{
				// store away isolate information
				breakIsolate = ((BreakEvent) e).isolateId;
				m_breakIsolates.add(breakIsolate);
				
				/** If this break event is due to a freshly loaded swf, 
				  * we need to mark it for showing prompt. */
				int reason = SuspendReason.Unknown;
				try { reason = m_session.getWorkerSession(breakIsolate).suspendReason(); } catch ( PlayerDebugException pde ) { }
				if ( reason == SuspendReason.ScriptLoaded ) {
					setPromptState(InitialPromptState.NEVER_SHOWN, breakIsolate);
				} 
				
				break;
			}
			else if (e instanceof FileListModifiedEvent)
			{
				// we ignore this
			}
			else if (e instanceof FunctionMetaDataAvailableEvent)
			{
				// we ignore this
			}
			else if (e instanceof FaultEvent)
			{
				breakIsolate = ((FaultEvent) e).isolateId;
				m_breakIsolates.add(breakIsolate);
				if ( handleFault((FaultEvent)e) )
					requestResume = true;
				else
					requestHalt = true;
				break;
			}
			else
			{
				Map<String, Object> args = new HashMap<String, Object>();
				args.put("type", e); //$NON-NLS-1$
				args.put("info", e.information); //$NON-NLS-1$
				err(getLocalizationManager().getLocalizedTextString("unknownEvent", args)); //$NON-NLS-1$
			}
		}

		// only if we have processed a fault which requested a resume and no other fault asked for a break
		// and we are suspended and it was due to us that the stop occurred!
		IsolateSession workerSession = null;
		if (m_session != null)
			workerSession = m_session.getWorkerSession(breakIsolate);
		if (requestResume && !requestHalt && workerSession != null && 
					workerSession.isSuspended() && workerSession.suspendReason() == SuspendReason.Fault)
			getIsolateState(breakIsolate).m_requestResume = true;
	}
	
	private void handleIsolateExitEvent(IsolateExitEvent e) {
		dumpIsolateExitLine(e);
	}

	private void handleIsolateCreateEvent(IsolateCreateEvent e) {
		dumpIsolateCreatedLine(e);
	}
	
	void dumpIsolateCreatedLine(IsolateCreateEvent e)
	{
		StringBuilder sb = new StringBuilder();
		sb.append(getLocalizationManager().getLocalizedTextString("linePrefixWhenWorkerCreated")); //$NON-NLS-1$
		sb.append(' ');
		sb.append(e.isolate.getId() - 1);
		out(sb.toString());
	}
	
	void dumpIsolateExitLine(IsolateExitEvent e)
	{
		StringBuilder sb = new StringBuilder();
		sb.append(getLocalizationManager().getLocalizedTextString("linePrefixWhenWorkerExit")); //$NON-NLS-1$
		sb.append(' ');
		sb.append(e.isolate.getId() - 1);
		out(sb.toString());
	}


	/**
	 * Our logic for handling a break condition.
	 *
	 * @return some hit breakpoint requested silence, shhhh!
	 */
	boolean processBreak(boolean postStep, StringBuilder sb, int isolateId) throws NotConnectedException
	{
		Location l = getCurrentLocationIsolate(isolateId);
		if (l == null || l.getFile() == null)
			return false;

		int fileId = l.getFile().getId();
		int line = l.getLine();
		boolean isSilent = false;
		boolean bpHit = false;
		boolean stoppedDueToBp = false;

		int count = breakpointCount();
		boolean[] markedForRemoval = new boolean[count];
		DebugCLIIsolateState state = getIsolateState(isolateId);
		boolean previousResume = state.m_requestResume;
		IsolateSession workerSession = m_session.getWorkerSession(isolateId);
		for(int i=0; i<count; i++)
		{
			BreakAction a = breakpointAt(i);
			if (a.locationMatches(fileId, line))
			{
				/**
				 * Note that it appears that we stopped due to hitting a hard breakpoint
				 * Now if the breakpoint is conditional it may eval to false, meaning we
				 * won't stop here, otherwise we will process the breakpoint.
				 */
				stoppedDueToBp = (workerSession.suspendReason() == SuspendReason.Breakpoint);
				if (shouldBreak(a, fileId, line, isolateId))
				{
					// its a hit
					bpHit = true;
					a.hit();
					isSilent = (isSilent) ? true : a.isSilent();

					// autodelete, autodisable
					if (a.isAutoDisable())
						disableBreakpointAt(i);

					if (a.isAutoDelete())
						markedForRemoval[i] = true;

					// now issue any commands that are attached to the breakpoint
					int n = a.getCommandCount();
					for(int j=0 ;j<n; j++)
						issueCommand(a.commandAt(j), sb);
				}
			}
		}

		// kill them backwards so our i is acurate
		for(int i=markedForRemoval.length-1; i>-1; i--)
			if (markedForRemoval[i])
				removeBreakpointAt(i);

		/**
		 * Now we should request to resume only if it was due to
		 * breakpoints that were hit.
		 *
		 * For the first case, we hit a conditional breakpoint that
		 * eval'd to false, resulting in bpHit == false.  Thus we
		 * want to resume and additionally if we were stepping, we'd
		 * like to do so 'softly' that is without loosing the stepping
		 * information on the Player.
		 *
		 * For the 2nd case, we hit a breakpoint and we executed
		 * commands that resulted in a m_requestResume.
		 */
		if (stoppedDueToBp && !bpHit)
		{
			state.m_requestResume = true;
			state.m_stepResume = postStep;    // resume without losing our stepping
			isSilent = true;			// do so quietly
		}
		else if (stoppedDueToBp && bpHit && state.m_requestResume && !previousResume)
		{
			state.m_requestResume = true;
			state.m_stepResume = postStep;    // resume as we would
		    processDisplay(sb);
		}

		// If we aren't continuing, then show display variables
		if (!state.m_requestResume)
			processDisplay(sb);

//		System.out.println("processBreak stopDueToBp="+stoppedDueToBp+",bpHit="+bpHit+",postStep="+postStep+",reason="+suspendReason());

		return isSilent;
	}

	// iterate through our display list entries
	void processDisplay(StringBuilder sb)
	{
		int count = displayCount();
		for(int i=0;i<count; i++)
		{
			DisplayAction a = displayAt(i);
			if (a.isEnabled())
			{
				try
				{
					sb.append(a.getId());
					sb.append(": "); //$NON-NLS-1$
					sb.append(a.getContent());
					sb.append(" = "); //$NON-NLS-1$

					// command[0] contains our expression, so first we parse it, evalulate it then print it
					Object result = m_exprCache.evaluate(a.getExpression(), a.getIsolateId()).value;

					if (result instanceof Variable)
						ExpressionCache.appendVariableValue(sb, ((Variable)result).getValue(), a.getIsolateId());

					else if (result instanceof Value)
						ExpressionCache.appendVariableValue(sb, (Value) result, a.getIsolateId());

					else if (result instanceof InternalProperty)
						sb.append( ((InternalProperty)result).valueOf() );

					else
						sb.append(result);

					sb.append(m_newline);
				}
				catch(NoSuchVariableException nsv)
				{
					Map<String, Object> args = new HashMap<String, Object>();
					args.put("variable", nsv.getMessage() ); //$NON-NLS-1$
					sb.append(getLocalizationManager().getLocalizedTextString("variableUnknown", args)); //$NON-NLS-1$
					sb.append(m_newline);
				}
				catch(NumberFormatException nfe)
				{
					Map<String, Object> args = new HashMap<String, Object>();
					args.put("value", nfe.getMessage() ); //$NON-NLS-1$
					sb.append(getLocalizationManager().getLocalizedTextString("couldNotConvertToNumber", args)); //$NON-NLS-1$
					sb.append(m_newline);
				}
				catch(PlayerFaultException pfe)
				{
					sb.append(pfe.getMessage() + m_newline);
				}
				catch (PlayerDebugException e)
				{
					sb.append(e.getMessage() + m_newline);
				}
				catch(NullPointerException npe)
				{
					sb.append(getLocalizationManager().getLocalizedTextString("couldNotEvaluate")); //$NON-NLS-1$
				}
			}
		}
	}

	/**
	 * Determines if the given BreakAction requests a halt given the file
	 * line and optionally a conditional to evaluate.'
	 */
	boolean shouldBreak(BreakAction a, int fileId, int line, int isolateId)
	{
		boolean should = a.isEnabled();
		ValueExp exp = a.getCondition();
		if (should && exp != null && !getRequestHalt(isolateId))  // halt request fires true
		{
			// evaluate it then update our boolean
			try
			{
				EvaluationResult result = evalExpression(exp, false, isolateId);
				if (result != null)
					should = ECMA.toBoolean(result.context.toValue(result.value));
			}
			catch(NullPointerException npe) {}
			catch(NumberFormatException nfe) {}
		}
		return should;
	}

	/**
	 * Sets the command interpreter up to execute the
	 * given string a  command
	 *
	 * This io redirection crap is really UGLY!!!
	 */
	void issueCommand(String cmd, StringBuilder output)
	{
		ByteArrayOutputStream ba = new ByteArrayOutputStream();
		PrintStream ps = new PrintStream(ba);

		// temporarily re-wire i/o to catch all output
		PrintStream oldOut = m_out;
		PrintStream oldErr = m_err;

		m_out = ps;
		m_err = ps;
		try
		{
			setCurrentLine(cmd);
			processLine();
		}
		catch(AmbiguousException ae)
		{
			// we already put up a warning for the user
		}
		catch(IllegalStateException ise)
		{
			err(getLocalizationManager().getLocalizedTextString("illegalStateException")); //$NON-NLS-1$
		}
		catch(IllegalMonitorStateException ime)
		{
			err(getLocalizationManager().getLocalizedTextString("commandNotValidUntilPlayerSuspended")); //$NON-NLS-1$
		}
		catch(NoSuchElementException nse)
		{
			err(getLocalizationManager().getLocalizedTextString("noSuchElementException")); //$NON-NLS-1$
		}
		catch(SocketException se)
		{
			Map<String, Object> args = new HashMap<String, Object>();
			args.put("socketErrorMessage", se.getMessage()); //$NON-NLS-1$
			err(getLocalizationManager().getLocalizedTextString("problemWithConnection", args)); //$NON-NLS-1$
		}
		catch(Exception e)
		{
			err(getLocalizationManager().getLocalizedTextString("unexpectedErrorWithStackTrace")); //$NON-NLS-1$
			if (Trace.error)
				e.printStackTrace();
		}

		// flush the stream and then send its contents to our string buffer
		ps.flush();
		output.append( ba.toString() );

		m_err = oldErr;
		m_out = oldOut;
	}

	/**
	 * We have received a fault and are possibly suspended at this point.
	 * We need to look at our fault table and determine what do.
	 * @return true if we resumed execution
	 */
	boolean handleFault(FaultEvent e)
	{
		// lookup what we need to do
		boolean requestResume = false;
		String name = e.name();
		boolean stop = true;
		boolean print = true;
		try
		{
			print = m_faultTable.is(name, "print"); //$NON-NLS-1$
			stop = m_faultTable.is(name, "stop"); //$NON-NLS-1$
		}
		catch(NullPointerException npe)
		{
			if (Trace.error)
			{
				Map<String, Object> args = new HashMap<String, Object>();
				args.put("faultName", name); //$NON-NLS-1$
				Trace.trace(getLocalizationManager().getLocalizedTextString("faultHasNoTableEntry", args)); //$NON-NLS-1$
				npe.printStackTrace();
			}
		}

		if (e instanceof ExceptionFault)
		{
			ExceptionFault ef = (ExceptionFault) e;
			Value thrownValue = ef.getThrownValue();
			if (thrownValue != null)
			{
				if (!ef.willExceptionBeCaught())
				{
					stop = true;
				}
				else
				{
					stop = false;

					String typeName = thrownValue.getTypeName();
					int at = typeName.indexOf('@');
					if (at != -1)
						typeName = typeName.substring(0, at);

					for (int i=0; i<catchpointCount(); ++i)
					{
						CatchAction c = catchpointAt(i);
						String typeToCatch = c.getTypeToCatch();
						try {
							if (typeToCatch == null || getSession().getWorkerSession(e.isolateId).evalIs(thrownValue, typeToCatch))
							{
								stop = true;
								break;
							}
						} catch (PlayerDebugException e1) {
							// TODO Auto-generated catch block
							e1.printStackTrace();
							stop = true;
						} catch (PlayerFaultException e1) {
							// TODO Auto-generated catch block
							e1.printStackTrace();
							stop = true;
						}
					}

					if (!stop)
						print = false;
				}
			}
		}

		// should we stop?
		if (!stop)
			requestResume = true;

		if (print)
			dumpFaultLine(e);

		return requestResume;
	}

	// wait a little bit of time until the player halts, if not throw an exception!
	void waitTilHalted(int isolateId) throws NotConnectedException
	{
		if (!haveConnection())
			throw new IllegalStateException();

		int timeout = propertyGet(HALT_TIMEOUT);
		int update = propertyGet(UPDATE_DELAY);
		boolean wait = (propertyGet(NO_WAITING) == 1) ? false : true;

		if (wait)
		{
			// spin for a while waiting for a halt; updating trace messages as we get them
			waitForSuspend(timeout, update, isolateId);

			if (!m_session.getWorkerSession(isolateId).isSuspended())
				throw new IllegalMonitorStateException();
		}
	}

	/**
	 * We spin in this spot until the player reaches the
	 * requested suspend state, either true or false.
	 *
	 * During this time we wake up every period milliseconds
	 * and update the display and our state with information
	 * received from the debug event queue.
	 */
	void waitForSuspend(int timeout, int period) throws NotConnectedException
	{
		waitForSuspend(timeout, period, Isolate.DEFAULT_ID);
	}
	
	/**
	 * We spin in this spot until the player reaches the
	 * requested suspend state, either true or false.
	 *
	 * During this time we wake up every period milliseconds
	 * and update the display and our state with information
	 * received from the debug event queue.
	 */
	void waitForSuspend(int timeout, int period, int isolateId) throws NotConnectedException
	{
		IsolateSession workerSession = m_session.getWorkerSession(isolateId);
		while(timeout > 0)
		{
			// dump our events to the console while we are waiting.
			processEvents();
			if (workerSession.isSuspended())
				break;

			try { Thread.sleep(period); } catch(InterruptedException ie) {}
			timeout -= period;
		}
	}

	/**
	 * If we still have a socket try to send an exit message
	 * Doesn't seem to work ?!?
	 */
	void exitSession()
	{
		// clear out our watchpoint list and displays
		// keep breakpoints around so that we can try to reapply them if we reconnect
		m_displays.clear();
		m_watchpoints.clear();

		if (m_fileInfo != null)
			m_fileInfo.unbind();

		if (m_session != null)
			m_session.terminate();

		m_session = null;
		m_fileInfo = null;
	}

	void initSession(Session s)
	{
		s.setSourceLocator(this);

		m_fileInfo = new FileInfoCache();
		m_exprCache.clear();

		m_fileInfo.bind(s);
		m_exprCache.bind(s);

		// bind catching a version problem
		boolean correctVersion = true;
		try { s.bind(); } catch(VersionException ve) { correctVersion = false; }

		// reset session properties
		propertyPut(LIST_LINE, 1);
		propertyPut(LIST_MODULE, 1);  // default to module #1
		propertyPut(BPNUM, 0); // set current breakpoint number as something bad
		propertyPut(LAST_FRAME_DEPTH, 0);
		propertyPut(CURRENT_FRAME_DEPTH, 0);
		propertyPut(DISPLAY_FRAME_NUMBER, 0);
		propertyPut(METADATA_ATTEMPTS_PERIOD, 250); // 1/4s per attempt
		propertyPut(METADATA_NOT_AVAILABLE, 0);  // counter for failures
		propertyPut(METADATA_ATTEMPTS, METADATA_RETRIES);
		propertyPut(PLAYER_FULL_SUPPORT, correctVersion ? 1 : 0);

		String previousURI = m_mruURI;
		m_mruURI = m_session.getURI();

		// try to reapply the breakpoint's
		if (previousURI != null && m_mruURI != null && previousURI.equalsIgnoreCase(m_mruURI))
			reapplyBreakpoints();
		else
		{
			while(m_breakpoints.size() > 0)
				m_breakpoints.removeElementAt(0);
		}

		m_mainState.m_requestResume = false;
		m_mainState.m_stepResume = false;
		initIsolateState();
	}

	private void initIsolateState() {
		m_activeIsolate = Isolate.DEFAULT_ID;
		m_breakIsolates = new Vector<Integer>();
		m_isolateState = new HashMap<Integer, DebugCLIIsolateState>();
		m_isolateState.put(Isolate.DEFAULT_ID, m_mainState);
	}

	/**
	 * Walk through the list of breakpoints and try to apply them to our session
	 * We aren't that smart in that we ignore the singleSwf property of the breakpoint
	 * meaning that if you have a breakpoint set on a single swf, it will be restored
	 * across all swfs.
	 */
	void reapplyBreakpoints()
	{
		// give us a bit of time to process the newly loaded swf
		if (propertyGet(METADATA_ATTEMPTS) > 0)
			try { waitForMetaData(80); } catch(InProgressException ipe) { }

		int count = breakpointCount();
		for(int i=0; i<count; i++)
		{
			BreakAction a = breakpointAt(i);
			a.clearHits();
			a.setStatus(BreakAction.UNRESOLVED);
		}

		StringBuilder sb = new StringBuilder();
		resolveBreakpoints(sb);
		out(sb.toString());
	}

	/**
	 * Process a single line of input and return true if the quit command was encountered
	 */
	public boolean processLine() throws IOException, AmbiguousException, PlayerDebugException
	{
		if (!hasMoreTokens())
			return false;

		String command = nextToken();
		boolean quit = false;
		int cmdID = commandFor(command);

		/* assume line will not be repeated. (i.e. user hits CR nothing happens) */
		m_repeatLine = null;

		switch(cmdID)
		{
			case CMD_QUIT:
				quit = doQuit();
				break;

			case CMD_CONTINUE:
				doContinue();
				break;

			case CMD_HOME:
				doHome();
				break;

			case CMD_HELP:
				doHelp();
				break;

			case CMD_SHOW:
				doShow();
				break;

			case CMD_STEP:
				doStep();
				break;

			case CMD_NEXT:
				doNext();
				break;

			case CMD_FINISH:
				doFinish();
				break;

			case CMD_BREAK:
				doBreak();
				break;

			case CMD_CLEAR:
				doClear();
				break;

			case CMD_SET:
				doSet();
				break;

			case CMD_LIST:
				doList();
				break;

			case CMD_PRINT:
				doPrint();
				break;

			case CMD_TUTORIAL:
				doTutorial();
				break;

			case CMD_INFO:
				doInfo();
				break;

			case CMD_FILE:
				doFile();
				break;

			case CMD_DELETE:
				doDelete();
				break;

			case CMD_RUN:
				doRun();
				break;

			case CMD_SOURCE:
				doSource();
				break;

			case CMD_KILL:
				doKill();
				break;

			case CMD_HANDLE:
				doHandle();
				break;

			case CMD_ENABLE:
				doEnable();
				break;

			case CMD_DISABLE:
				doDisable();
				break;

			case CMD_DISPLAY:
				doDisplay();
				break;

			case CMD_UNDISPLAY:
				doUnDisplay();
				break;

			case CMD_COMMANDS:
				doCommands();
				break;

			case CMD_PWD:
				doPWD();
				break;

			case CMD_CF:
				doCF();
				break;

//			case CMD_AWATCH:
//				doWatch(true, true);
//				break;

			case CMD_WATCH:
				doWatch(false, true);
				break;

//			case CMD_RWATCH:
//				doWatch(true, false);
//				break;

            case CMD_CONDITION:
                doCondition();
                break;

            case CMD_WHAT:
                doWhat();
                break;

            case CMD_DISASSEMBLE:
                doDisassemble();
                break;

            case CMD_HALT:
                doHalt();
                break;

            case CMD_MCTREE:
                doMcTree();
                break;

            case CMD_VIEW_SWF:
                doViewSwf();
                break;

            case CMD_DOWN:
                doDown();
                break;

            case CMD_UP:
                doUp();
                break;

            case CMD_FRAME:
                doFrame();
                break;

			case CMD_COMMENT:
				; // nop
				break;

			case INFO_STACK_CMD:
				; // from bt
				doInfoStack();
				break;

			case CMD_DIRECTORY:
				doDirectory();
				break;

			case CMD_CATCH:
				doCatch();
				break;

			case CMD_CONNECT:
				doConnect();
				break;
				
			case CMD_WORKER:
				doWorker();
				break;

			default:
				doUnknown(command);
				break;
		}
		return quit;
	}

	void doWorker() throws IOException, NotSupportedException, NotSuspendedException, NoResponseException, NotConnectedException
	{
		if (hasMoreTokens()) {
			String isolateid = nextToken();
			if (isolateid != null && isolateid.length() > 0) {
				try {
					int id = Integer.parseInt(isolateid);
					id++;
					boolean found = false;
					for (Isolate isolate : m_session.getWorkers()) {
						if (isolate.getId() == id)
							found = true;
					}
					StringBuilder sb = new StringBuilder();
					if (found) {
						m_activeIsolate = id;
						propertyPut(LIST_WORKER, id);
						propertyPut(LIST_LINE, 1);
						propertyPut(LIST_MODULE, 1);  // default to module #1
						propertyPut(BPNUM, 0); // set current breakpoint number as something bad
						propertyPut(LAST_FRAME_DEPTH, 0);
						propertyPut(CURRENT_FRAME_DEPTH, 0);
						propertyPut(DISPLAY_FRAME_NUMBER, 0);
						sb.append(getLocalizationManager().getLocalizedTextString("workerChanged") + " "); //$NON-NLS-1$ //$NON-NLS-2$
						if (id == Isolate.DEFAULT_ID) {
							sb.append(getLocalizationManager().getLocalizedTextString("mainThread")); //$NON-NLS-1$
						}
						else
							sb.append((id - 1));
						sb.append(m_newline);
					}
					else {
						sb.append(getLocalizationManager().getLocalizedTextString("workerNotFound") + " " + (id - 1)); //$NON-NLS-1$ //$NON-NLS-2$
						sb.append(m_newline);
					}
					out(sb.toString());
				}
				catch(NumberFormatException e) {
					err(e.getLocalizedMessage());
				}
			}
		}
	}

	
    /**
     * Read help text from fdbhelp*.txt.
     */
    String getHelpTopic(String topic)
    {
        // Open the file fdbhelp*.txt that is a sibling of this class file.
        // (Note: build.xml copies it into the classes directory.)
        InputStream helpStream = Help.getResourceAsStream();
        if (helpStream == null)
            return getLocalizationManager().getLocalizedTextString("noHelpFileFound"); //$NON-NLS-1$

        // Read the help file line-by-line, looking for topic lines like [Break].
        // Build an array of the lines within the section for the specified topic.
        topic = "[" + topic + "]"; //$NON-NLS-1$ //$NON-NLS-2$
        Vector<String> lines = new Vector<String>();
        BufferedReader r = null;
        try
        {
            r = new BufferedReader(new InputStreamReader(helpStream, "UTF-8")); //$NON-NLS-1$
            String line;
            // Read lines until we find the specified topic line.
            while ((line = r.readLine()) != null)
            {
                if (line.startsWith(topic))
                    break;
            }
            // Read lines until we find the next topic line.
            while ((line = r.readLine()) != null)
            {
                 if (line.startsWith("[")) //$NON-NLS-1$
                     break;
                 lines.add(line);
            }
        }
        catch(FileNotFoundException fnf)
		{
			err(fnf.getLocalizedMessage());
		}
        catch(IOException e)
		{
			err(e.getLocalizedMessage());
		}
        finally
        {
        	if (r != null)
				try { r.close(); } catch (IOException e) { e.printStackTrace(); }
        }

        // Concatenate the lines, leaving out the first and last ones
        // which are supposed to be blank. They're only there to make
        // fdbhelp*.txt more readable.
        StringBuilder helpText = new StringBuilder();
        int n = lines.size();
        for (int i = 1; i < n - 1; i++)
        {
            String line = lines.get(i);
            helpText.append(line);
            if (i != n - 2)
                helpText.append(m_newline);
        }

        return helpText.toString();
    }

	/**
	 * Provide contenxt sensistive help
	 */
	void doHelp() throws AmbiguousException
	{
        // someone entered a help command so let's help them!
		String topic = "help"; //$NON-NLS-1$

        int cmd;
        String commandName;

        // they might have entered something like "help br"
        if (hasMoreTokens())
		{
			// map "br" to CMD_BREAK
            cmd = commandFor(nextToken());
             // and then back to "break"
            commandName = commandNumberToCommandName(g_commandArray, cmd);
            // so we'll look up the topic named "break" in fdbhelp*.txt
            topic = commandName;

            // they might have entered something like "help inf fil"
            if (cmd == CMD_INFO && hasMoreTokens())
            {
                // map "fil" to CMD_INFO_FILE
                cmd = infoCommandFor(nextToken());
                // and then back to "file"
                commandName = commandNumberToCommandName(g_infoCommandArray, cmd);
                // so we'll look up the topic named "info file" in fdbhelp*.txt
                 topic += " " +  commandName; //$NON-NLS-1$
            }

            // or like "help sho n"
            else if (cmd == CMD_SHOW && hasMoreTokens())
            {
                // map "n" to CMD_SHOW_NET
                cmd = showCommandFor(nextToken());
                // and then back to "net"
                commandName = commandNumberToCommandName(g_showCommandArray, cmd);
                // so we'll look up the topic named "show net" in fdbhelp*.txt
                topic += " " + commandName; //$NON-NLS-1$
            }
		}

		out( getHelpTopic(topic) );
	}

    void doTutorial()
	{
		out( getHelpTopic("Tutorial") ); //$NON-NLS-1$
	}

	// process strings to command ids
	int commandFor(String s) throws AmbiguousException			{ return determineCommand(g_commandArray, s, CMD_UNKNOWN);	}
	int showCommandFor(String s) throws AmbiguousException		{ return determineCommand(g_showCommandArray, s, SHOW_UNKNOWN_CMD);	}
	int infoCommandFor(String s) throws AmbiguousException		{ return determineCommand(g_infoCommandArray, s, INFO_UNKNOWN_CMD);	}
	int enableCommandFor(String s) throws AmbiguousException	{ return determineCommand(g_enableCommandArray, s, CMD_UNKNOWN);	}
	int disableCommandFor(String s) throws AmbiguousException	{ return determineCommand(g_disableCommandArray, s, CMD_UNKNOWN);	}

	/**
	 * Attempt to match given the given string against our set of commands
	 * @return the command code that was hit.
	 */
	int determineCommand(StringIntArray cmdList, String input, int defCmd) throws AmbiguousException
	{
		int cmd = defCmd;

		// first check for a comment
		if (input.charAt(0) == '#')
			cmd = CMD_COMMENT;
		else
		{
//			long start = System.currentTimeMillis();
			ArrayList ar = cmdList.elementsStartingWith(input);
//			long end = System.currentTimeMillis();

			int size = ar.size();

			/**
			 * 3 cases:
			 *  - No hits, return unknown and let our caller
			 *    dump the error.
			 *  - We match unambiguously or we have 1 or more matches
			 *    and the input is a single character. We then take the
			 *    first hit as our command.
			 *  - If we have multiple hits then we dump a 'ambiguous' message
			 *    and puke quietly.
			 */
			if (size == 0)
				; // no command match return unknown

			// only 1 match or our input is 1 character or first match is exact
			else if (size == 1 ||
					 input.length() == 1 ||
					 cmdList.getString( ((Integer)ar.get(0)).intValue() ).compareTo(input) == 0)
			{
				cmd = (cmdList.getInteger( ((Integer)ar.get(0)).intValue() )).intValue();
			}
			else
			{
				// matches more than one command dump message and go
				StringBuilder sb = new StringBuilder();
				Map<String, Object> args = new HashMap<String, Object>();
				args.put("input", input); //$NON-NLS-1$
				sb.append(getLocalizationManager().getLocalizedTextString("ambiguousCommand", args)); //$NON-NLS-1$
				sb.append(' ');
				sb.append(input);
				for(int i=0; i<size; i++)
				{
					String s = cmdList.getString( ((Integer)ar.get(i)).intValue() );
					sb.append(s);
					if (i+1 < size)
						sb.append(", "); //$NON-NLS-1$
				}
				sb.append('.');
				err( sb.toString() );
				throw new AmbiguousException();
			}
		}
		return cmd;
	}

    String commandNumberToCommandName(StringIntArray cmdList, int cmdNumber)
    {
        for (int i = 0; i < cmdList.size(); i++)
        {
            if (cmdList.getInt(i) == cmdNumber)
                return cmdList.getString(i);
        }

        return "?"; //$NON-NLS-1$
    }

	/**
	 * The array of top level commands that we support.
	 * They are placed into a Nx2 array, whereby the first component
	 * is a String which is the command and the 2nd component is the
	 * integer identifier for the command.
	 *
	 * The StringIntArray object provides a convenient wrapper class
	 * that implements the List interface.
	 *
	 * NOTE: order matters!  For the case of a single character
	 *       match, we let the first hit act like an unambiguous match.
	 */
	static StringIntArray g_commandArray = new StringIntArray( new Object[][]
	{
		{ "awatch", new Integer(CMD_AWATCH) }, //$NON-NLS-1$
		{ "break", new Integer(CMD_BREAK) }, //$NON-NLS-1$
		{ "bt", new Integer(INFO_STACK_CMD) }, //$NON-NLS-1$
        { "continue", new Integer(CMD_CONTINUE) }, //$NON-NLS-1$
        { "catch", new Integer(CMD_CATCH) }, //$NON-NLS-1$
        { "cf", new Integer(CMD_CF) }, //$NON-NLS-1$
		{ "clear", new Integer(CMD_CLEAR) }, //$NON-NLS-1$
		{ "commands", new Integer(CMD_COMMANDS) }, //$NON-NLS-1$
		{ "condition", new Integer(CMD_CONDITION) }, //$NON-NLS-1$
		{ "connect", new Integer(CMD_CONNECT) }, //$NON-NLS-1$
		{ "delete", new Integer(CMD_DELETE) }, //$NON-NLS-1$
		{ "disable", new Integer(CMD_DISABLE) }, //$NON-NLS-1$
		{ "disassemble", new Integer(CMD_DISASSEMBLE) }, //$NON-NLS-1$
		{ "display", new Integer(CMD_DISPLAY) }, //$NON-NLS-1$
		{ "directory", new Integer(CMD_DIRECTORY) }, //$NON-NLS-1$
        { "down", new Integer(CMD_DOWN) }, //$NON-NLS-1$
		{ "enable", new Integer(CMD_ENABLE) }, //$NON-NLS-1$
		{ "finish", new Integer(CMD_FINISH) }, //$NON-NLS-1$
		{ "file", new Integer(CMD_FILE) }, //$NON-NLS-1$
        { "frame", new Integer(CMD_FRAME) }, //$NON-NLS-1$
		{ "help", new Integer(CMD_HELP) }, //$NON-NLS-1$
		{ "halt", new Integer(CMD_HALT) }, //$NON-NLS-1$
		{ "handle", new Integer(CMD_HANDLE) }, //$NON-NLS-1$
		{ "home", new Integer(CMD_HOME) }, //$NON-NLS-1$
		{ "info", new Integer(CMD_INFO) }, //$NON-NLS-1$
		{ "kill", new Integer(CMD_KILL) }, //$NON-NLS-1$
		{ "list", new Integer(CMD_LIST) }, //$NON-NLS-1$
		{ "next", new Integer(CMD_NEXT) }, //$NON-NLS-1$
		{ "nexti", new Integer(CMD_NEXT) }, //$NON-NLS-1$
		{ "mctree", new Integer(CMD_MCTREE) }, //$NON-NLS-1$
        { "print", new Integer(CMD_PRINT) }, //$NON-NLS-1$
        { "pwd", new Integer(CMD_PWD) }, //$NON-NLS-1$
		{ "quit", new Integer(CMD_QUIT) }, //$NON-NLS-1$
		{ "run", new Integer(CMD_RUN) }, //$NON-NLS-1$
		{ "rwatch", new Integer(CMD_RWATCH) }, //$NON-NLS-1$
		{ "step", new Integer(CMD_STEP) }, //$NON-NLS-1$
		{ "stepi", new Integer(CMD_STEP) }, //$NON-NLS-1$
		{ "set", new Integer(CMD_SET) }, //$NON-NLS-1$
		{ "show", new Integer(CMD_SHOW) }, //$NON-NLS-1$
		{ "source", new Integer(CMD_SOURCE) }, //$NON-NLS-1$
		{ "tutorial", new Integer(CMD_TUTORIAL) }, //$NON-NLS-1$
		{ "undisplay", new Integer(CMD_UNDISPLAY) }, //$NON-NLS-1$
        { "up", new Integer(CMD_UP) }, //$NON-NLS-1$
		{ "where", new Integer(INFO_STACK_CMD) }, //$NON-NLS-1$
		{ "watch", new Integer(CMD_WATCH) }, //$NON-NLS-1$
		{ "what", new Integer(CMD_WHAT) }, //$NON-NLS-1$
		{ "viewswf", new Integer(CMD_VIEW_SWF) }, //$NON-NLS-1$
		{ "worker", new Integer(CMD_WORKER) }, //$NON-NLS-1$

	} );

	/**
	 * Info sub-commands
	 */
	static StringIntArray g_infoCommandArray = new StringIntArray( new Object[][]
	{
		{ "arguments", new Integer(INFO_ARGS_CMD) }, //$NON-NLS-1$
		{ "breakpoints", new Integer(INFO_BREAK_CMD) }, //$NON-NLS-1$
		{ "display", new Integer(INFO_DISPLAY_CMD) }, //$NON-NLS-1$
		{ "files", new Integer(INFO_FILES_CMD) }, //$NON-NLS-1$
		{ "functions", new Integer(INFO_FUNCTIONS_CMD) }, //$NON-NLS-1$
		{ "handle", new Integer(INFO_HANDLE_CMD) }, //$NON-NLS-1$
		{ "locals", new Integer(INFO_LOCALS_CMD) }, //$NON-NLS-1$
		{ "stack", new Integer(INFO_STACK_CMD) }, //$NON-NLS-1$
		{ "scopechain", new Integer(INFO_SCOPECHAIN_CMD) }, //$NON-NLS-1$
        { "sources", new Integer(INFO_SOURCES_CMD) }, //$NON-NLS-1$
        { "swfs", new Integer(INFO_SWFS_CMD) }, //$NON-NLS-1$
        { "targets", new Integer(INFO_TARGETS_CMD) }, //$NON-NLS-1$
		{ "variables", new Integer(INFO_VARIABLES_CMD) }, //$NON-NLS-1$
		{ "workers", new Integer(INFO_WORKERS_CMD) }, //$NON-NLS-1$
	} );

	/**
	 * Show sub-commands
	 */
	static StringIntArray g_showCommandArray = new StringIntArray( new Object[][]
	{
		{ "break", new Integer(SHOW_BREAK_CMD) }, //$NON-NLS-1$
		{ "directories", new Integer(SHOW_DIRS_CMD) }, //$NON-NLS-1$
		{ "files", new Integer(SHOW_FILES_CMD) }, //$NON-NLS-1$
		{ "functions", new Integer(SHOW_FUNC_CMD) }, //$NON-NLS-1$
		{ "locations", new Integer(SHOW_LOC_CMD) }, //$NON-NLS-1$
		{ "memory", new Integer(SHOW_MEM_CMD) }, //$NON-NLS-1$
		{ "net", new Integer(SHOW_NET_CMD) }, //$NON-NLS-1$
		{ "properties", new Integer(SHOW_PROPERTIES_CMD) }, //$NON-NLS-1$
		{ "uri", new Integer(SHOW_URI_CMD) }, //$NON-NLS-1$
		{ "variable", new Integer(SHOW_VAR_CMD) }, //$NON-NLS-1$
	} );

	/**
	 * enable sub-commands
	 */
	static StringIntArray g_enableCommandArray = new StringIntArray( new Object[][]
	{
		{ "breakpoints", new Integer(CMD_BREAK) }, //$NON-NLS-1$
		{ "display", new Integer(CMD_DISPLAY) }, //$NON-NLS-1$
		{ "delete", new Integer(CMD_DELETE) }, //$NON-NLS-1$
		{ "once", new Integer(ENABLE_ONCE_CMD) }, //$NON-NLS-1$
	} );

	/**
	 * disable sub-commands
	 */
	static StringIntArray g_disableCommandArray = new StringIntArray( new Object[][]
	{
		{ "display", new Integer(CMD_DISPLAY) }, //$NON-NLS-1$
		{ "breakpoints", new Integer(CMD_BREAK) }, //$NON-NLS-1$
	} );


	/**
	 * -------------------------------------------------------------------------
	 * Any code that accesses the implementation of the API is wrapped 
	 * in Extensions.  This way one can easily factor this stuff out
	 * and build an fdb that is completely compliant to the API.
	 *
	 * I'm pretty sure there's a better way of doing this like
	 * making Extensions a final static variable and then 
	 * toggling it between two classes Extensions and something
	 * like ExtensionsDisabled (methods with only out("not supported")
	 * in them).
	 * -------------------------------------------------------------------------
	 */
	void appendBreakInfo(StringBuilder sb, int isolateId) throws NotConnectedException	{ Extensions.appendBreakInfo(this, sb, false, isolateId);	}
	void doShowStats()													{ Extensions.doShowStats(this);					}
	void doShowFuncs()													{ Extensions.doShowFuncs(this);					}
	void doShowProperties()												{ Extensions.doShowProperties(this);			}
	void doShowVariable() throws PlayerDebugException					{ Extensions.doShowVariable(this);				}
	void doShowBreak() throws NotConnectedException						{ Extensions.doShowBreak(this);					}
 	void doDisassemble() throws PlayerDebugException					{ Extensions.doDisassemble(this);				}
}
